pax_global_header00006660000000000000000000000064141733127150014516gustar00rootroot0000000000000052 comment=76f68fb70731c74f195884c51168cffceae575b7 orson-charts-2.1.0/000077500000000000000000000000001417331271500141405ustar00rootroot00000000000000orson-charts-2.1.0/.github/000077500000000000000000000000001417331271500155005ustar00rootroot00000000000000orson-charts-2.1.0/.github/workflows/000077500000000000000000000000001417331271500175355ustar00rootroot00000000000000orson-charts-2.1.0/.github/workflows/ci.yaml000066400000000000000000000010531417331271500210130ustar00rootroot00000000000000--- name: Java CI on: [push] jobs: test: runs-on: ${{ matrix.os }} strategy: matrix: os: [ubuntu-18.04, macOS-latest, windows-2016] java: [11, 11.0.3, 12, 13, 13.0.4, 14, 15, 16-ea] fail-fast: false max-parallel: 4 name: Test JDK ${{ matrix.java }}, ${{ matrix.os }} steps: - uses: actions/checkout@v1 - name: Set up JDK uses: actions/setup-java@v1 with: java-version: ${{ matrix.java }} - name: Test with Maven run: mvn test -B --file pom.xml ...orson-charts-2.1.0/.gitignore000066400000000000000000000001511417331271500161250ustar00rootroot00000000000000*.class # Package Files # *.jar *.war *.ear /target/ *.DS_Store .idea nb-configuration.xml nbactions.xmlorson-charts-2.1.0/LICENSE000066400000000000000000001045151417331271500151530ustar00rootroot00000000000000 GNU GENERAL PUBLIC LICENSE Version 3, 29 June 2007 Copyright (C) 2007 Free Software Foundation, Inc. Everyone is permitted to copy and distribute verbatim copies of this license document, but changing it is not allowed. Preamble The GNU General Public License is a free, copyleft license for software and other kinds of works. The licenses for most software and other practical works are designed to take away your freedom to share and change the works. By contrast, the GNU General Public License is intended to guarantee your freedom to share and change all versions of a program--to make sure it remains free software for all its users. We, the Free Software Foundation, use the GNU General Public License for most of our software; it applies also to any other work released this way by its authors. You can apply it to your programs, too. When we speak of free software, we are referring to freedom, not price. Our General Public Licenses are designed to make sure that you have the freedom to distribute copies of free software (and charge for them if you wish), that you receive source code or can get it if you want it, that you can change the software or use pieces of it in new free programs, and that you know you can do these things. To protect your rights, we need to prevent others from denying you these rights or asking you to surrender the rights. Therefore, you have certain responsibilities if you distribute copies of the software, or if you modify it: responsibilities to respect the freedom of others. For example, if you distribute copies of such a program, whether gratis or for a fee, you must pass on to the recipients the same freedoms that you received. You must make sure that they, too, receive or can get the source code. And you must show them these terms so they know their rights. Developers that use the GNU GPL protect your rights with two steps: (1) assert copyright on the software, and (2) offer you this License giving you legal permission to copy, distribute and/or modify it. For the developers' and authors' protection, the GPL clearly explains that there is no warranty for this free software. For both users' and authors' sake, the GPL requires that modified versions be marked as changed, so that their problems will not be attributed erroneously to authors of previous versions. Some devices are designed to deny users access to install or run modified versions of the software inside them, although the manufacturer can do so. This is fundamentally incompatible with the aim of protecting users' freedom to change the software. The systematic pattern of such abuse occurs in the area of products for individuals to use, which is precisely where it is most unacceptable. Therefore, we have designed this version of the GPL to prohibit the practice for those products. If such problems arise substantially in other domains, we stand ready to extend this provision to those domains in future versions of the GPL, as needed to protect the freedom of users. Finally, every program is threatened constantly by software patents. States should not allow patents to restrict development and use of software on general-purpose computers, but in those that do, we wish to avoid the special danger that patents applied to a free program could make it effectively proprietary. To prevent this, the GPL assures that patents cannot be used to render the program non-free. The precise terms and conditions for copying, distribution and modification follow. TERMS AND CONDITIONS 0. Definitions. "This License" refers to version 3 of the GNU General Public License. "Copyright" also means copyright-like laws that apply to other kinds of works, such as semiconductor masks. "The Program" refers to any copyrightable work licensed under this License. Each licensee is addressed as "you". "Licensees" and "recipients" may be individuals or organizations. To "modify" a work means to copy from or adapt all or part of the work in a fashion requiring copyright permission, other than the making of an exact copy. The resulting work is called a "modified version" of the earlier work or a work "based on" the earlier work. A "covered work" means either the unmodified Program or a work based on the Program. To "propagate" a work means to do anything with it that, without permission, would make you directly or secondarily liable for infringement under applicable copyright law, except executing it on a computer or modifying a private copy. Propagation includes copying, distribution (with or without modification), making available to the public, and in some countries other activities as well. To "convey" a work means any kind of propagation that enables other parties to make or receive copies. Mere interaction with a user through a computer network, with no transfer of a copy, is not conveying. An interactive user interface displays "Appropriate Legal Notices" to the extent that it includes a convenient and prominently visible feature that (1) displays an appropriate copyright notice, and (2) tells the user that there is no warranty for the work (except to the extent that warranties are provided), that licensees may convey the work under this License, and how to view a copy of this License. If the interface presents a list of user commands or options, such as a menu, a prominent item in the list meets this criterion. 1. Source Code. The "source code" for a work means the preferred form of the work for making modifications to it. "Object code" means any non-source form of a work. A "Standard Interface" means an interface that either is an official standard defined by a recognized standards body, or, in the case of interfaces specified for a particular programming language, one that is widely used among developers working in that language. The "System Libraries" of an executable work include anything, other than the work as a whole, that (a) is included in the normal form of packaging a Major Component, but which is not part of that Major Component, and (b) serves only to enable use of the work with that Major Component, or to implement a Standard Interface for which an implementation is available to the public in source code form. A "Major Component", in this context, means a major essential component (kernel, window system, and so on) of the specific operating system (if any) on which the executable work runs, or a compiler used to produce the work, or an object code interpreter used to run it. The "Corresponding Source" for a work in object code form means all the source code needed to generate, install, and (for an executable work) run the object code and to modify the work, including scripts to control those activities. However, it does not include the work's System Libraries, or general-purpose tools or generally available free programs which are used unmodified in performing those activities but which are not part of the work. For example, Corresponding Source includes interface definition files associated with source files for the work, and the source code for shared libraries and dynamically linked subprograms that the work is specifically designed to require, such as by intimate data communication or control flow between those subprograms and other parts of the work. The Corresponding Source need not include anything that users can regenerate automatically from other parts of the Corresponding Source. The Corresponding Source for a work in source code form is that same work. 2. Basic Permissions. All rights granted under this License are granted for the term of copyright on the Program, and are irrevocable provided the stated conditions are met. This License explicitly affirms your unlimited permission to run the unmodified Program. The output from running a covered work is covered by this License only if the output, given its content, constitutes a covered work. This License acknowledges your rights of fair use or other equivalent, as provided by copyright law. You may make, run and propagate covered works that you do not convey, without conditions so long as your license otherwise remains in force. You may convey covered works to others for the sole purpose of having them make modifications exclusively for you, or provide you with facilities for running those works, provided that you comply with the terms of this License in conveying all material for which you do not control copyright. Those thus making or running the covered works for you must do so exclusively on your behalf, under your direction and control, on terms that prohibit them from making any copies of your copyrighted material outside their relationship with you. Conveying under any other circumstances is permitted solely under the conditions stated below. Sublicensing is not allowed; section 10 makes it unnecessary. 3. Protecting Users' Legal Rights From Anti-Circumvention Law. No covered work shall be deemed part of an effective technological measure under any applicable law fulfilling obligations under article 11 of the WIPO copyright treaty adopted on 20 December 1996, or similar laws prohibiting or restricting circumvention of such measures. When you convey a covered work, you waive any legal power to forbid circumvention of technological measures to the extent such circumvention is effected by exercising rights under this License with respect to the covered work, and you disclaim any intention to limit operation or modification of the work as a means of enforcing, against the work's users, your or third parties' legal rights to forbid circumvention of technological measures. 4. Conveying Verbatim Copies. You may convey verbatim copies of the Program's source code as you receive it, in any medium, provided that you conspicuously and appropriately publish on each copy an appropriate copyright notice; keep intact all notices stating that this License and any non-permissive terms added in accord with section 7 apply to the code; keep intact all notices of the absence of any warranty; and give all recipients a copy of this License along with the Program. You may charge any price or no price for each copy that you convey, and you may offer support or warranty protection for a fee. 5. Conveying Modified Source Versions. You may convey a work based on the Program, or the modifications to produce it from the Program, in the form of source code under the terms of section 4, provided that you also meet all of these conditions: a) The work must carry prominent notices stating that you modified it, and giving a relevant date. b) The work must carry prominent notices stating that it is released under this License and any conditions added under section 7. This requirement modifies the requirement in section 4 to "keep intact all notices". c) You must license the entire work, as a whole, under this License to anyone who comes into possession of a copy. This License will therefore apply, along with any applicable section 7 additional terms, to the whole of the work, and all its parts, regardless of how they are packaged. This License gives no permission to license the work in any other way, but it does not invalidate such permission if you have separately received it. d) If the work has interactive user interfaces, each must display Appropriate Legal Notices; however, if the Program has interactive interfaces that do not display Appropriate Legal Notices, your work need not make them do so. A compilation of a covered work with other separate and independent works, which are not by their nature extensions of the covered work, and which are not combined with it such as to form a larger program, in or on a volume of a storage or distribution medium, is called an "aggregate" if the compilation and its resulting copyright are not used to limit the access or legal rights of the compilation's users beyond what the individual works permit. Inclusion of a covered work in an aggregate does not cause this License to apply to the other parts of the aggregate. 6. Conveying Non-Source Forms. You may convey a covered work in object code form under the terms of sections 4 and 5, provided that you also convey the machine-readable Corresponding Source under the terms of this License, in one of these ways: a) Convey the object code in, or embodied in, a physical product (including a physical distribution medium), accompanied by the Corresponding Source fixed on a durable physical medium customarily used for software interchange. b) Convey the object code in, or embodied in, a physical product (including a physical distribution medium), accompanied by a written offer, valid for at least three years and valid for as long as you offer spare parts or customer support for that product model, to give anyone who possesses the object code either (1) a copy of the Corresponding Source for all the software in the product that is covered by this License, on a durable physical medium customarily used for software interchange, for a price no more than your reasonable cost of physically performing this conveying of source, or (2) access to copy the Corresponding Source from a network server at no charge. c) Convey individual copies of the object code with a copy of the written offer to provide the Corresponding Source. This alternative is allowed only occasionally and noncommercially, and only if you received the object code with such an offer, in accord with subsection 6b. d) Convey the object code by offering access from a designated place (gratis or for a charge), and offer equivalent access to the Corresponding Source in the same way through the same place at no further charge. You need not require recipients to copy the Corresponding Source along with the object code. If the place to copy the object code is a network server, the Corresponding Source may be on a different server (operated by you or a third party) that supports equivalent copying facilities, provided you maintain clear directions next to the object code saying where to find the Corresponding Source. Regardless of what server hosts the Corresponding Source, you remain obligated to ensure that it is available for as long as needed to satisfy these requirements. e) Convey the object code using peer-to-peer transmission, provided you inform other peers where the object code and Corresponding Source of the work are being offered to the general public at no charge under subsection 6d. A separable portion of the object code, whose source code is excluded from the Corresponding Source as a System Library, need not be included in conveying the object code work. A "User Product" is either (1) a "consumer product", which means any tangible personal property which is normally used for personal, family, or household purposes, or (2) anything designed or sold for incorporation into a dwelling. In determining whether a product is a consumer product, doubtful cases shall be resolved in favor of coverage. For a particular product received by a particular user, "normally used" refers to a typical or common use of that class of product, regardless of the status of the particular user or of the way in which the particular user actually uses, or expects or is expected to use, the product. A product is a consumer product regardless of whether the product has substantial commercial, industrial or non-consumer uses, unless such uses represent the only significant mode of use of the product. "Installation Information" for a User Product means any methods, procedures, authorization keys, or other information required to install and execute modified versions of a covered work in that User Product from a modified version of its Corresponding Source. The information must suffice to ensure that the continued functioning of the modified object code is in no case prevented or interfered with solely because modification has been made. If you convey an object code work under this section in, or with, or specifically for use in, a User Product, and the conveying occurs as part of a transaction in which the right of possession and use of the User Product is transferred to the recipient in perpetuity or for a fixed term (regardless of how the transaction is characterized), the Corresponding Source conveyed under this section must be accompanied by the Installation Information. But this requirement does not apply if neither you nor any third party retains the ability to install modified object code on the User Product (for example, the work has been installed in ROM). The requirement to provide Installation Information does not include a requirement to continue to provide support service, warranty, or updates for a work that has been modified or installed by the recipient, or for the User Product in which it has been modified or installed. Access to a network may be denied when the modification itself materially and adversely affects the operation of the network or violates the rules and protocols for communication across the network. Corresponding Source conveyed, and Installation Information provided, in accord with this section must be in a format that is publicly documented (and with an implementation available to the public in source code form), and must require no special password or key for unpacking, reading or copying. 7. Additional Terms. "Additional permissions" are terms that supplement the terms of this License by making exceptions from one or more of its conditions. Additional permissions that are applicable to the entire Program shall be treated as though they were included in this License, to the extent that they are valid under applicable law. If additional permissions apply only to part of the Program, that part may be used separately under those permissions, but the entire Program remains governed by this License without regard to the additional permissions. When you convey a copy of a covered work, you may at your option remove any additional permissions from that copy, or from any part of it. (Additional permissions may be written to require their own removal in certain cases when you modify the work.) You may place additional permissions on material, added by you to a covered work, for which you have or can give appropriate copyright permission. Notwithstanding any other provision of this License, for material you add to a covered work, you may (if authorized by the copyright holders of that material) supplement the terms of this License with terms: a) Disclaiming warranty or limiting liability differently from the terms of sections 15 and 16 of this License; or b) Requiring preservation of specified reasonable legal notices or author attributions in that material or in the Appropriate Legal Notices displayed by works containing it; or c) Prohibiting misrepresentation of the origin of that material, or requiring that modified versions of such material be marked in reasonable ways as different from the original version; or d) Limiting the use for publicity purposes of names of licensors or authors of the material; or e) Declining to grant rights under trademark law for use of some trade names, trademarks, or service marks; or f) Requiring indemnification of licensors and authors of that material by anyone who conveys the material (or modified versions of it) with contractual assumptions of liability to the recipient, for any liability that these contractual assumptions directly impose on those licensors and authors. All other non-permissive additional terms are considered "further restrictions" within the meaning of section 10. If the Program as you received it, or any part of it, contains a notice stating that it is governed by this License along with a term that is a further restriction, you may remove that term. If a license document contains a further restriction but permits relicensing or conveying under this License, you may add to a covered work material governed by the terms of that license document, provided that the further restriction does not survive such relicensing or conveying. If you add terms to a covered work in accord with this section, you must place, in the relevant source files, a statement of the additional terms that apply to those files, or a notice indicating where to find the applicable terms. Additional terms, permissive or non-permissive, may be stated in the form of a separately written license, or stated as exceptions; the above requirements apply either way. 8. Termination. You may not propagate or modify a covered work except as expressly provided under this License. Any attempt otherwise to propagate or modify it is void, and will automatically terminate your rights under this License (including any patent licenses granted under the third paragraph of section 11). However, if you cease all violation of this License, then your license from a particular copyright holder is reinstated (a) provisionally, unless and until the copyright holder explicitly and finally terminates your license, and (b) permanently, if the copyright holder fails to notify you of the violation by some reasonable means prior to 60 days after the cessation. Moreover, your license from a particular copyright holder is reinstated permanently if the copyright holder notifies you of the violation by some reasonable means, this is the first time you have received notice of violation of this License (for any work) from that copyright holder, and you cure the violation prior to 30 days after your receipt of the notice. Termination of your rights under this section does not terminate the licenses of parties who have received copies or rights from you under this License. If your rights have been terminated and not permanently reinstated, you do not qualify to receive new licenses for the same material under section 10. 9. Acceptance Not Required for Having Copies. You are not required to accept this License in order to receive or run a copy of the Program. Ancillary propagation of a covered work occurring solely as a consequence of using peer-to-peer transmission to receive a copy likewise does not require acceptance. However, nothing other than this License grants you permission to propagate or modify any covered work. These actions infringe copyright if you do not accept this License. Therefore, by modifying or propagating a covered work, you indicate your acceptance of this License to do so. 10. Automatic Licensing of Downstream Recipients. Each time you convey a covered work, the recipient automatically receives a license from the original licensors, to run, modify and propagate that work, subject to this License. You are not responsible for enforcing compliance by third parties with this License. An "entity transaction" is a transaction transferring control of an organization, or substantially all assets of one, or subdividing an organization, or merging organizations. If propagation of a covered work results from an entity transaction, each party to that transaction who receives a copy of the work also receives whatever licenses to the work the party's predecessor in interest had or could give under the previous paragraph, plus a right to possession of the Corresponding Source of the work from the predecessor in interest, if the predecessor has it or can get it with reasonable efforts. You may not impose any further restrictions on the exercise of the rights granted or affirmed under this License. For example, you may not impose a license fee, royalty, or other charge for exercise of rights granted under this License, and you may not initiate litigation (including a cross-claim or counterclaim in a lawsuit) alleging that any patent claim is infringed by making, using, selling, offering for sale, or importing the Program or any portion of it. 11. Patents. A "contributor" is a copyright holder who authorizes use under this License of the Program or a work on which the Program is based. The work thus licensed is called the contributor's "contributor version". A contributor's "essential patent claims" are all patent claims owned or controlled by the contributor, whether already acquired or hereafter acquired, that would be infringed by some manner, permitted by this License, of making, using, or selling its contributor version, but do not include claims that would be infringed only as a consequence of further modification of the contributor version. For purposes of this definition, "control" includes the right to grant patent sublicenses in a manner consistent with the requirements of this License. Each contributor grants you a non-exclusive, worldwide, royalty-free patent license under the contributor's essential patent claims, to make, use, sell, offer for sale, import and otherwise run, modify and propagate the contents of its contributor version. In the following three paragraphs, a "patent license" is any express agreement or commitment, however denominated, not to enforce a patent (such as an express permission to practice a patent or covenant not to sue for patent infringement). To "grant" such a patent license to a party means to make such an agreement or commitment not to enforce a patent against the party. If you convey a covered work, knowingly relying on a patent license, and the Corresponding Source of the work is not available for anyone to copy, free of charge and under the terms of this License, through a publicly available network server or other readily accessible means, then you must either (1) cause the Corresponding Source to be so available, or (2) arrange to deprive yourself of the benefit of the patent license for this particular work, or (3) arrange, in a manner consistent with the requirements of this License, to extend the patent license to downstream recipients. "Knowingly relying" means you have actual knowledge that, but for the patent license, your conveying the covered work in a country, or your recipient's use of the covered work in a country, would infringe one or more identifiable patents in that country that you have reason to believe are valid. If, pursuant to or in connection with a single transaction or arrangement, you convey, or propagate by procuring conveyance of, a covered work, and grant a patent license to some of the parties receiving the covered work authorizing them to use, propagate, modify or convey a specific copy of the covered work, then the patent license you grant is automatically extended to all recipients of the covered work and works based on it. A patent license is "discriminatory" if it does not include within the scope of its coverage, prohibits the exercise of, or is conditioned on the non-exercise of one or more of the rights that are specifically granted under this License. You may not convey a covered work if you are a party to an arrangement with a third party that is in the business of distributing software, under which you make payment to the third party based on the extent of your activity of conveying the work, and under which the third party grants, to any of the parties who would receive the covered work from you, a discriminatory patent license (a) in connection with copies of the covered work conveyed by you (or copies made from those copies), or (b) primarily for and in connection with specific products or compilations that contain the covered work, unless you entered into that arrangement, or that patent license was granted, prior to 28 March 2007. Nothing in this License shall be construed as excluding or limiting any implied license or other defenses to infringement that may otherwise be available to you under applicable patent law. 12. No Surrender of Others' Freedom. If conditions are imposed on you (whether by court order, agreement or otherwise) that contradict the conditions of this License, they do not excuse you from the conditions of this License. If you cannot convey a covered work so as to satisfy simultaneously your obligations under this License and any other pertinent obligations, then as a consequence you may not convey it at all. For example, if you agree to terms that obligate you to collect a royalty for further conveying from those to whom you convey the Program, the only way you could satisfy both those terms and this License would be to refrain entirely from conveying the Program. 13. Use with the GNU Affero General Public License. Notwithstanding any other provision of this License, you have permission to link or combine any covered work with a work licensed under version 3 of the GNU Affero General Public License into a single combined work, and to convey the resulting work. The terms of this License will continue to apply to the part which is the covered work, but the special requirements of the GNU Affero General Public License, section 13, concerning interaction through a network will apply to the combination as such. 14. Revised Versions of this License. The Free Software Foundation may publish revised and/or new versions of the GNU General Public License from time to time. Such new versions will be similar in spirit to the present version, but may differ in detail to address new problems or concerns. Each version is given a distinguishing version number. If the Program specifies that a certain numbered version of the GNU General Public License "or any later version" applies to it, you have the option of following the terms and conditions either of that numbered version or of any later version published by the Free Software Foundation. If the Program does not specify a version number of the GNU General Public License, you may choose any version ever published by the Free Software Foundation. If the Program specifies that a proxy can decide which future versions of the GNU General Public License can be used, that proxy's public statement of acceptance of a version permanently authorizes you to choose that version for the Program. Later license versions may give you additional or different permissions. However, no additional obligations are imposed on any author or copyright holder as a result of your choosing to follow a later version. 15. Disclaimer of Warranty. THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION. 16. Limitation of Liability. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. 17. Interpretation of Sections 15 and 16. If the disclaimer of warranty and limitation of liability provided above cannot be given local legal effect according to their terms, reviewing courts shall apply local law that most closely approximates an absolute waiver of all civil liability in connection with the Program, unless a warranty or assumption of liability accompanies a copy of the Program in return for a fee. END OF TERMS AND CONDITIONS How to Apply These Terms to Your New Programs If you develop a new program, and you want it to be of the greatest possible use to the public, the best way to achieve this is to make it free software which everyone can redistribute and change under these terms. To do so, attach the following notices to the program. It is safest to attach them to the start of each source file to most effectively state the exclusion of warranty; and each file should have at least the "copyright" line and a pointer to where the full notice is found. Copyright (C) This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program. If not, see . Also add information on how to contact you by electronic and paper mail. If the program does terminal interaction, make it output a short notice like this when it starts in an interactive mode: Copyright (C) This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'. This is free software, and you are welcome to redistribute it under certain conditions; type `show c' for details. The hypothetical commands `show w' and `show c' should show the appropriate parts of the General Public License. Of course, your program's commands might be different; for a GUI interface, you would use an "about box". You should also get your employer (if you work as a programmer) or school, if any, to sign a "copyright disclaimer" for the program, if necessary. For more information on this, and how to apply and follow the GNU GPL, see . The GNU General Public License does not permit incorporating your program into proprietary programs. If your program is a subroutine library, you may consider it more useful to permit linking proprietary applications with the library. If this is what you want to do, use the GNU Lesser General Public License instead of this License. But first, please read . orson-charts-2.1.0/README.md000066400000000000000000000151251417331271500154230ustar00rootroot00000000000000Orson Charts ============ (C)opyright 2013-2022, by David Gilbert. All rights reserved. Version 2.1.0, 23 January 2022. ### Overview Orson Charts is a 3D chart library for the Java™ platform that can generate a wide variety of 3D charts for use in client-side applications (JavaFX and Swing) and server-side applications (with export to PDF, SVG, PNG and JPEG). JFree Demo for Orson Charts Key features include: - multiple chart types: pie charts, bar charts (regular and stacked), line charts, area charts, scatter charts and surface plots; - mouse-enabled chart viewers in JavaFX and Swing provide 360 degree rotation and zooming for precise end-user view control; - configurable tool tip support; - interactive charts (mouse event support on all chart elements); - flexible data sources; - JSON format data import and export; - regular and logarithmic axis scales; - auto-adaptive axis labeling; - value and range marker annotations - support for PDF, SVG, PNG and JPG export of charts for reporting; - a clean and well-documented API with a high degree of chart configurability. Orson Charts is very easy to use, and includes comprehensive [Javadocs](https://www.javadoc.io/doc/org.jfree/org.jfree.chart3d/latest/org.jfree.chart3d/module-summary.html). It is licensed under the terms of the GNU General Public License version 3 or later. Orson Charts requires JDK/JRE 11 or later. To use Orson Charts with JavaFX requires the [Orson Charts FX](https://github.com/jfree/orson-charts-fx) extension project. ### Demos Demo applications can be found in the following projects at GitHub: * [JFree-Demos](https://github.com/jfree/jfree-demos "JFree-Demos Project Page at GitHub") * [JFree-FXDemos](https://github.com/jfree/jfree-fxdemos "JFree-FXDemos Project Page at GitHub") ### Building You can build Orson Charts using Maven by issuing the following command from the root directory of the project: mvn clean install The build requires JDK 11 or later. ### Reporting Bugs If you find a bug in Orson Charts, please file a bug report at: https://github.com/jfree/orson-charts/issues ### History #### Version 2.1.0 : 23-Jan-2022 - bug fix - axis ranges not being updated correctly. See issue [#9](https://github.com/jfree/orson-charts/issues/9) - clean-up - fix numerous warnings/hints highlighted by IntelliJ IDEA. - dependencies - upgraded JUnit to version 5; - build - set plugin versions in `pom.xml`. #### Version 2.0 : 15-Mar-2020 - created a Java module (`org.jfree.chart3d`); - refactored into `org.jfree.chart3d` namespace; - fixed bug [#4](https://github.com/jfree/orson-charts/issues/4) in `NumberAxis3D` where tick label override is not applied. #### Version 1.7 : 17-Nov-2017 - removed JavaFX support to a separate project [Orson Charts FX](https://github.com/jfree/orson-charts-fx); - fixed cell content bug in `GridElement`; - fixed bug in `GradientColorScale`; - protect from `NullPointerException` in `AbstractValueAxis3D`; - streamline build by removing Ant build support and moving demo code to external projects. #### Version 1.6 : 2-Nov-2016 - added `remove()` method to `XYZSeries` and added change notification mechanism; - added `remove()` and `removeAll()` methods to `XYZSeriesCollection` and added change notification; - added generics to source files; - updated `FXGraphics2D` to version 1.5; - updated `JFreeSVG` to version 3.2. #### Version 1.5 : 28-Jan-2016 - added new `LineXYZRenderer`; - added option to invert axes; - fix exception when setting a new dataset using `CategoryPlot3D.setDataset()`: - fix direction of mouse wheel zooming in JavaFX; - included FXGraphics2D version 1.3 as a dependency; - updated OrsonPDF to version 1.7; - updated JFreeSVG to version 3.0; - added `pom.xml` for Maven builds; - JavaFX demos brought up to match the Swing demos; - various Javadoc improvements. #### Version 1.4 : 27-May-2014 - added JavaFX support; - added support to marker elements and item labels for `KEY_BEGIN_ELEMENT` and `KEY_END_ELEMENT` rendering hints; - added `JPEG` export option; - added `minAutoRangeLength` attribute in `AbstractValueAxis3D` (this fixes a bug for plots where the length of the data range is zero, for example scatter plots with a single value); - fixed endless loop in axis range code for datasets with infinite values; - fixed bug in hinting for tick labels on `NumberAxis3D`; - fixed `Utils.js` functions that didn't work with Internet Explorer 9. #### Version 1.3 : 11-Apr-2014 - added chart mouse event and tooltip support for the chart viewer in Swing; - added item label support; - added `JSON` format data import and export; - new utility methods to extract an `XYZDataset` from a `CategoryDataset3D`; - fixed a clipping issue for panels with borders assigned; - added rendering hints for SVG output via JFreeSVG (to support tool-tips and mouse events on chart elements); - added JavaScript utility library to support JFreeSVG export; #### Version 1.2 : 7-Mar-2014 - added value and range markers for numerical axes, and category markers for category axes; - added a `tickLabelOrientation` attribute for axes so that tick labels can be drawn either perpendicular or parallel to the axis line; - added a logarithmic axis; - added theme support, with several built-in themes; - added template driven label generators for pie section labels and category axis labels; - added export to `JPEG`, plus options to configure the available export types; - optimized the rendering code to reduce memory usage; - put in place a localisation mechanism, and added German and Italian translations; - made the projection distance configurable in the chart viewer; - added series accessors for `XYZSeriesCollection`; - added `yDimensionOverride` attribute for `CategoryPlot3D`; - fixed an issue with the `StackedBarRenderer` and negative values; - incorporated various other bug fixes. #### Version 1.1 : 23-Dec-2013 - added surface plots (via the new `SurfaceRenderer` class and `Chart3DFactory.createSurfaceChart()`); - added `ColorScale` and supporting classes for use by the surface charts; - added orientation attribute to control the chart legend orientation; - optimized rendering code for improved performance; - added missing change events for gridline attributes in `CategoryPlot3D`; - added constants including `SCALE_TO_FIT_TARGET` and `CENTER_NO_SCALING` to the `Fit2D` class; - added `setColors(Color...)` to `AbstractCategoryRenderer3D` and `AbstractXYZRenderer3D`; #### Version 1.0 : 17-Nov-2013 This is the first public release of Orson Charts, we welcome your feedback and suggestions. orson-charts-2.1.0/js/000077500000000000000000000000001417331271500145545ustar00rootroot00000000000000orson-charts-2.1.0/js/README.txt000066400000000000000000000007361417331271500162600ustar00rootroot00000000000000JavaScript Utilities -------------------- This directory contains some JavaScript utility code that can be used when exporting charts to SVG format with JFreeSVG. The build.sh script will build the library, but note that it requires the Google Closure Compiler jar file to be on the classpath (please edit the script accordingly). https://developers.google.com/closure/compiler/ Look in the 'svg' directory (open SVGDemo1.html) to see a demo that uses this JavaScript code. orson-charts-2.1.0/js/build.sh000077500000000000000000000005211417331271500162100ustar00rootroot00000000000000#!/bin/bash java -jar ~/jars/compiler.jar --warning_level VERBOSE --compilation_level WHITESPACE_ONLY \ --js src/Utils.js \ --js src/KeyedValuesDataset.js \ --js src/KeyedValues3DDataset.js \ --js src/XYZDataset.js \ --js src/KeyedValueLabels.js \ --js src/KeyedValue3DLabels.js \ --js src/XYZLabels.js \ --js_output_file orsoncharts.jsorson-charts-2.1.0/js/orsoncharts.js000066400000000000000000000310151417331271500174570ustar00rootroot00000000000000var orsoncharts;if(!orsoncharts)orsoncharts={};orsoncharts.Utils={};orsoncharts.Utils.makeArrayOf=function(value,length){var arr=[],i=length;while(i--)arr[i]=value;return arr};orsoncharts.Utils.findChartRef=function(element){var id=element.getAttribute("jfreesvg:ref");var found=false;var current=element;while(!found){current=current.parentNode;if(current!=null){id=current.getAttribute("jfreesvg:ref");found=id!=null}else found=true}return id}; orsoncharts.Utils.findChartId=function(element){var id=null;var found=false;var current=element;while(!found){current=current.parentNode;if(current!=null){var ref=current.getAttribute("jfreesvg:ref");if(ref=="ORSON_CHART_TOP_LEVEL"){found=true;id=current.getAttribute("id")}}else found=true}return id};if(!orsoncharts)orsoncharts={};orsoncharts.KeyedValuesDataset=function(){if(!(this instanceof orsoncharts.KeyedValuesDataset))return new orsoncharts.KeyedValuesDataset;this.data=[];this.listeners=[]};orsoncharts.KeyedValuesDataset.prototype.itemCount=function(){return this.data.length};orsoncharts.KeyedValuesDataset.prototype.isEmpty=function(){return this.data.length===0};orsoncharts.KeyedValuesDataset.prototype.key=function(index){return this.data[index][0]}; orsoncharts.KeyedValuesDataset.prototype.keys=function(){return this.data.map(function(d){return d[0]})};orsoncharts.KeyedValuesDataset.prototype.indexOf=function(sectionKey){var arrayLength=this.data.length;for(var i=0;i=0)this.listeners.splice(i,1)}; orsoncharts.KeyedValuesDataset.prototype.notifyListeners=function(){};orsoncharts.KeyedValuesDataset.prototype.add=function(sectionKey,value){this.data.push([sectionKey,value])};orsoncharts.KeyedValuesDataset.prototype.remove=function(sectionKey){if(!sectionKey)throw new Error("The 'sectionKey' must be defined.");var i=this.indexOf(sectionKey);if(i<0)throw new Error("The sectionKey '"+sectionKey.toString()+"' is not recognised.");this.data.splice(i,1)}; orsoncharts.KeyedValuesDataset.prototype.dataFromJSON=function(jsonStr){this.data=JSON.parse(jsonStr);this.notifyListeners()};orsoncharts.KeyedValuesDataset.prototype.removeByIndex=function(itemIndex){this.data.splice(itemIndex,1)};orsoncharts.KeyedValuesDataset.prototype.totalForDataset=function(dataset){var total=0;var itemCount=dataset.itemCount();for(var i=0;i=0)this.listeners.splice(i,1)};orsoncharts.KeyedValues3DDataset.prototype.notifyListeners=function(){}; orsoncharts.KeyedValues3DDataset.prototype.add=function(seriesKey,rowKey,columnKey,value){if(this.isEmpty()){this.data.rowKeys.push(rowKey);this.data.columnKeys.push(columnKey);this.data.series.push({"seriesKey":seriesKey,"rows":[[rowKey,[value]]]})}else{var seriesIndex=this.seriesIndex(seriesKey);if(seriesIndex<0){this.data.series.push({"seriesKey":seriesKey,"rows":[]});seriesIndex=this.data.series.length-1}var columnIndex=this.columnIndex(columnKey);if(columnIndex<0){this.data.columnKeys.push(columnKey); for(var s=0;s=0)throw new Error("There is already a series with the key '"+seriesKey);this.data["series"].push([seriesKey,[]])}; orsoncharts.XYZDataset.prototype.removeSeries=function(seriesKey){if(!(typeof seriesKey==="string"))throw new Error("The 'seriesKey' must be a string.");var s=this.seriesIndex(seriesKey);if(s>=0)this.data["series"].splice(s,1)};orsoncharts.XYZDataset.prototype.addListener=function(listenerMethod){this.listeners.push(listenerMethod)};orsoncharts.XYZDataset.prototype.removeListener=function(listenerMethod){var i=this.listeners.indexOf(listenerMethod);if(i>=0)this.listeners.splice(i,1)};if(!orsoncharts)orsoncharts={};orsoncharts.KeyedValueLabels=function(){if(!(this instanceof orsoncharts.KeyedValueLabels))return new orsoncharts.KeyedValueLabels;this.format="{K} = {V}";this.valueDP=2;this.percentDP=2}; orsoncharts.KeyedValueLabels.prototype.itemLabel=function(keyedValues,itemIndex){var labelStr=new String(this.format);var keyStr=keyedValues.key(itemIndex);var value=keyedValues.valueByIndex(itemIndex);var valueStr=value.toFixed(this.valueDP);var total=keyedValues.total();var percentStr=(value/total*100).toFixed(this.percentDP);labelStr=labelStr.replace(/{K}/g,keyStr);labelStr=labelStr.replace(/{V}/g,valueStr);labelStr=labelStr.replace(/{P}/g,percentStr);return labelStr};if(!orsoncharts)orsoncharts={};orsoncharts.KeyedValue3DLabels=function(){if(!(this instanceof orsoncharts.KeyedValue3DLabels))return new orsoncharts.KeyedValue3DLabels;this.format="{S}, {R}, {C} = {V}";this.valueDP=2}; orsoncharts.KeyedValue3DLabels.prototype.itemLabel=function(keyedValues3D,seriesIndex,rowIndex,columnIndex){var labelStr=new String(this.format);var seriesKeyStr=keyedValues3D.seriesKey(seriesIndex);var rowKeyStr=keyedValues3D.rowKey(rowIndex);var columnKeyStr=keyedValues3D.columnKey(columnIndex);var value=keyedValues3D.valueByIndex(seriesIndex,rowIndex,columnIndex);var valueStr=value.toFixed(this.valueDP);labelStr=labelStr.replace(/{S}/g,seriesKeyStr);labelStr=labelStr.replace(/{R}/g,rowKeyStr); labelStr=labelStr.replace(/{C}/g,columnKeyStr);labelStr=labelStr.replace(/{V}/g,valueStr);return labelStr};if(!orsoncharts)orsoncharts={};orsoncharts.XYZLabels=function(){if(!(this instanceof orsoncharts.XYZLabels))return new orsoncharts.XYZLabels;this.format="{X}, {Y}, {Z} / {S}";this.xDP=2;this.yDP=2;this.zDP=2}; orsoncharts.XYZLabels.prototype.itemLabel=function(dataset,seriesKey,itemIndex){var labelStr=new String(this.format);var seriesKeyStr=seriesKey;var seriesIndex=dataset.seriesIndex(seriesKey);var item=dataset.item(seriesIndex,itemIndex);var xStr=item[0].toFixed(this.xDP);var yStr=item[1].toFixed(this.yDP);var zStr=item[2].toFixed(this.zDP);labelStr=labelStr.replace(/{X}/g,xStr);labelStr=labelStr.replace(/{Y}/g,yStr);labelStr=labelStr.replace(/{Z}/g,zStr);labelStr=labelStr.replace(/{S}/g,seriesKeyStr); return labelStr}; orson-charts-2.1.0/js/src/000077500000000000000000000000001417331271500153435ustar00rootroot00000000000000orson-charts-2.1.0/js/src/KeyedValue3DLabels.js000066400000000000000000000022621417331271500212530ustar00rootroot00000000000000/* * Orson Charts * ------------ * Copyright 2014-2022 by David Gilbert. */ "use strict"; if (!orsoncharts) orsoncharts = {}; /** * Constructor for a new KeyedValue3DLabels instance * @constructor */ orsoncharts.KeyedValue3DLabels = function() { if (!(this instanceof orsoncharts.KeyedValue3DLabels)) { return new orsoncharts.KeyedValue3DLabels(); } this.format = "{S}, {R}, {C} = {V}"; this.valueDP = 2; }; // Generates a label for an item in a KeyedValue3DDataset. orsoncharts.KeyedValue3DLabels.prototype.itemLabel = function(keyedValues3D, seriesIndex, rowIndex, columnIndex) { var labelStr = new String(this.format); var seriesKeyStr = keyedValues3D.seriesKey(seriesIndex); var rowKeyStr = keyedValues3D.rowKey(rowIndex); var columnKeyStr = keyedValues3D.columnKey(columnIndex); var value = keyedValues3D.valueByIndex(seriesIndex, rowIndex, columnIndex); var valueStr = value.toFixed(this.valueDP); labelStr = labelStr.replace(/{S}/g, seriesKeyStr); labelStr = labelStr.replace(/{R}/g, rowKeyStr); labelStr = labelStr.replace(/{C}/g, columnKeyStr); labelStr = labelStr.replace(/{V}/g, valueStr); return labelStr; };orson-charts-2.1.0/js/src/KeyedValueLabels.js000066400000000000000000000020431417331271500210610ustar00rootroot00000000000000/* * Orson Charts * ------------ * Copyright 2014-2022 by David Gilbert. */ "use strict"; if (!orsoncharts) orsoncharts = {}; /** * Constructor for a new KeyedValueLabels instance * @constructor */ orsoncharts.KeyedValueLabels = function() { if (!(this instanceof orsoncharts.KeyedValueLabels)) { return new orsoncharts.KeyedValueLabels(); } this.format = "{K} = {V}"; this.valueDP = 2; this.percentDP = 2; }; // Generates a label for an item in a KeyedValuesDataset. orsoncharts.KeyedValueLabels.prototype.itemLabel = function(keyedValues, itemIndex) { var labelStr = new String(this.format); var keyStr = keyedValues.key(itemIndex); var value = keyedValues.valueByIndex(itemIndex); var valueStr = value.toFixed(this.valueDP); var total = keyedValues.total(); var percentStr = (value / total * 100).toFixed(this.percentDP); labelStr = labelStr.replace(/{K}/g, keyStr); labelStr = labelStr.replace(/{V}/g, valueStr); labelStr = labelStr.replace(/{P}/g, percentStr); return labelStr; }; orson-charts-2.1.0/js/src/KeyedValues3DDataset.js000066400000000000000000000153721417331271500216270ustar00rootroot00000000000000/* * Copyright 2014-2022 by David Gilbert. */ if (!orsoncharts) orsoncharts = {}; /** * Constructor for a new KeyedValuesDataset3D * @constructor */ orsoncharts.KeyedValues3DDataset = function() { if (!(this instanceof orsoncharts.KeyedValues3DDataset)) { return new orsoncharts.KeyedValues3DDataset(); } this.data = { "columnKeys": [], "rowKeys": [], "series": [] }; this.listeners = []; }; // Returns true if the dataset is empty and false otherwise. orsoncharts.KeyedValues3DDataset.prototype.isEmpty = function() { return this.data["columnKeys"].length === 0 && this.data["rowKeys"].length === 0; }; // Returns the number of series in the dataset. orsoncharts.KeyedValues3DDataset.prototype.seriesCount = function() { return this.data.series.length; }; // Returns the number of rows in the dataset. orsoncharts.KeyedValues3DDataset.prototype.rowCount = function() { return this.data.rowKeys.length; }; // Returns the number of columns in the dataset. orsoncharts.KeyedValues3DDataset.prototype.columnCount = function() { return this.data["columnKeys"].length; }; orsoncharts.KeyedValues3DDataset.prototype._fetchRow = function(seriesIndex, rowKey) { var rows = this.data.series[seriesIndex].rows; for (var r = 0; r < rows.length; r++) { if (rows[r][0] === rowKey) { return rows[r]; } } return null; }; // Returns a value by series, row and column index. orsoncharts.KeyedValues3DDataset.prototype.valueByIndex = function(seriesIndex, rowIndex, columnIndex) { var rowKey = this.rowKey(rowIndex); var row = this._fetchRow(seriesIndex, rowKey); if (row === null) { return null; } else { return row[1][columnIndex]; } }; // Returns the index of the series with the specified key, or -1. orsoncharts.KeyedValues3DDataset.prototype.seriesIndex = function(seriesKey) { var seriesCount = this.seriesCount(); for (var s = 0; s < seriesCount; s++) { if (this.data.series[s].seriesKey === seriesKey) { return s; } } return -1; }; // Returns the key for the series with the specified index. orsoncharts.KeyedValues3DDataset.prototype.seriesKey = function(seriesIndex) { return this.data.series[seriesIndex].seriesKey; }; // Returns the key for the row with the specified index. orsoncharts.KeyedValues3DDataset.prototype.rowKey = function(rowIndex) { return this.data.rowKeys[rowIndex]; }; // Returns the index of the row with the specified key. orsoncharts.KeyedValues3DDataset.prototype.rowIndex = function(rowKey) { var rowCount = this.data.rowKeys.length; for (var r = 0; r < rowCount; r++) { if (this.data.rowKeys[r] === rowKey) { return r; } } return -1; }; // Returns all the row keys. orsoncharts.KeyedValues3DDataset.prototype.rowKeys = function() { return this.data.rowKeys.map(function(d) { return d; }); }; // Returns the key for the column with the specified index. orsoncharts.KeyedValues3DDataset.prototype.columnKey = function(columnIndex) { return this.data.columnKeys[columnIndex]; }; // Returns the index of hte column with the specified key. orsoncharts.KeyedValues3DDataset.prototype.columnIndex = function(columnKey) { var columnCount = this.data.columnKeys.length; for (var c = 0; c < columnCount; c++) { if (this.data.columnKeys[c] === columnKey) { return c; } } return -1; }; // Returns all the column keys. orsoncharts.KeyedValues3DDataset.prototype.columnKeys = function() { return this.data.columnKeys.map(function(d) { return d; }); }; // Returns the value for the item identified by the specified series, row and // column keys. orsoncharts.KeyedValues3DDataset.prototype.valueByKey = function(seriesKey, rowKey, columnKey) { var seriesIndex = this.seriesIndex(seriesKey); var row = this._fetchRow(seriesIndex, rowKey); if (row === null) { return null; } else { var columnIndex = this.columnIndex(columnKey); return row[1][columnIndex]; } }; // Adds a listener to the dataset (the listener method will be called whenever // the dataset is modified) orsoncharts.KeyedValues3DDataset.prototype.addListener = function(listenerMethod) { this.listeners.push(listenerMethod); }; // Deregisters the specified listener so that it no longer receives // notification of dataset changes orsoncharts.KeyedValues3DDataset.prototype.removeListener = function(listenerMethod) { var i = this.listeners.indexOf(listenerMethod); if (i >= 0) { this.listeners.splice(i, 1); } }; // Notifies all registered listeners that there has been a change to this dataset orsoncharts.KeyedValues3DDataset.prototype.notifyListeners = function() { // TODO: call each listenerMethod }; // adds a value to the dataset (or updates an existing value) orsoncharts.KeyedValues3DDataset.prototype.add = function(seriesKey, rowKey, columnKey, value) { if (this.isEmpty()) { this.data.rowKeys.push(rowKey); this.data.columnKeys.push(columnKey); this.data.series.push({"seriesKey": seriesKey, "rows": [[rowKey, [value]]]}); } else { var seriesIndex = this.seriesIndex(seriesKey); if (seriesIndex < 0) { this.data.series.push({"seriesKey": seriesKey, "rows": []}); seriesIndex = this.data.series.length - 1; } var columnIndex = this.columnIndex(columnKey); if (columnIndex < 0) { // add the column key and insert a null data item in all existing rows this.data.columnKeys.push(columnKey); for (var s = 0; s < this.data.series.length; s++) { var rows = this.data.series[s].rows; for (var r = 0; r < rows.length; r++) { rows[r][1].push(null); } } columnIndex = this.columnCount() - 1; } var rowIndex = this.rowIndex(rowKey); if (rowIndex < 0) { this.data.rowKeys.push(rowKey); // add the row for the current series only var rowData = orsoncharts.Utils.makeArrayOf(null, this.columnCount()); rowData[columnIndex] = value; this.data.series[seriesIndex].rows.push([rowKey, rowData]); } else { var row = this._fetchRow(seriesIndex, rowKey); if (row !== null) { row[1][columnIndex] = value; } else { var rowData = orsoncharts.Utils.makeArrayOf(null, this.columnCount()); rowData[columnIndex] = value; this.data.series[seriesIndex].rows.push([rowKey, rowData]); } } } }; orsoncharts.KeyedValues3DDataset.prototype.dataFromJSON = function(jsonStr) { this.data = JSON.parse(jsonStr); if (!this.data.hasOwnProperty("rowKeys")) { this.data.rowKeys = []; } if (!this.data.hasOwnProperty("columnKeys")) { this.data.columnKeys = []; } if (!this.data.hasOwnProperty("series")) { this.data.series = []; } this.notifyListeners(); }; orson-charts-2.1.0/js/src/KeyedValuesDataset.js000066400000000000000000000116771417331271500214440ustar00rootroot00000000000000/* * Copyright 2014-2022 by David Gilbert. */ "use strict"; if (!orsoncharts) orsoncharts = {}; /** * Constructor for a new KeyedValuesDataset * @constructor */ orsoncharts.KeyedValuesDataset = function() { if (!(this instanceof orsoncharts.KeyedValuesDataset)) { return new orsoncharts.KeyedValuesDataset(); } this.data = []; this.listeners = []; }; // returns the number of items in the dataset orsoncharts.KeyedValuesDataset.prototype.itemCount = function() { return this.data.length; }; // Returns true if the dataset contains no items and false otherwise orsoncharts.KeyedValuesDataset.prototype.isEmpty = function() { return this.data.length === 0; }; // returns the section key for the item with the specified index. orsoncharts.KeyedValuesDataset.prototype.key = function(index) { return this.data[index][0]; }; // Returns a new array containing all the keys for the dataset. orsoncharts.KeyedValuesDataset.prototype.keys = function() { return this.data.map(function(d) { return d[0]; }); }; // returns the index of the item with the specified key, or -1 orsoncharts.KeyedValuesDataset.prototype.indexOf = function(sectionKey) { var arrayLength = this.data.length; for (var i = 0; i < arrayLength; i++) { if (this.data[i][0] === sectionKey) { return i; } } return -1; }; // returns the value for the item with the specified index. orsoncharts.KeyedValuesDataset.prototype.valueByIndex = function(index) { return this.data[index][1]; }; // returns the value for the item with the specified key orsoncharts.KeyedValuesDataset.prototype.valueByKey = function(sectionKey) { var sectionIndex = this.indexOf(sectionKey); if (sectionIndex < 0) return null; return this.valueByIndex(sectionIndex); }; // Adds a listener to the dataset (the listener method will be called whenever // the dataset is modified) orsoncharts.KeyedValuesDataset.prototype.addListener = function(listenerMethod) { this.listeners.push(listenerMethod); }; // Deregisters the specified listener so that it no longer receives // notification of dataset changes orsoncharts.KeyedValuesDataset.prototype.removeListener = function(listenerMethod) { var i = this.listeners.indexOf(listenerMethod); if (i >= 0) { this.listeners.splice(i, 1); } }; // Notifies all registered listeners that there has been a change to this dataset orsoncharts.KeyedValuesDataset.prototype.notifyListeners = function() { // TODO: call each listenerMethod }; // adds the specified (key, value) pair to the dataset or, if the key exists // already, updates the value orsoncharts.KeyedValuesDataset.prototype.add = function(sectionKey, value) { this.data.push([sectionKey, value]); }; // removes the item with the specified key orsoncharts.KeyedValuesDataset.prototype.remove = function(sectionKey) { if (!sectionKey) throw new Error("The 'sectionKey' must be defined."); var i = this.indexOf(sectionKey); if (i < 0) throw new Error("The sectionKey '" + sectionKey.toString() + "' is not recognised."); this.data.splice(i, 1); }; // sets the data array based on the supplied JSON string orsoncharts.KeyedValuesDataset.prototype.dataFromJSON = function(jsonStr) { this.data = JSON.parse(jsonStr); this.notifyListeners(); }; orsoncharts.KeyedValuesDataset.prototype.removeByIndex = function(itemIndex) { this.data.splice(itemIndex, 1); }; // returns the total of all non-null values for the specified dataset orsoncharts.KeyedValuesDataset.prototype.totalForDataset = function(dataset) { var total = 0.0; var itemCount = dataset.itemCount(); for (var i = 0; i < itemCount; i++) { var v = dataset.valueByIndex(i); if (v) { total = total + v; } } return total; }; // returns the minimum value for the specified dataset orsoncharts.KeyedValuesDataset.prototype.minForDataset = function(dataset) { var min = null; var itemCount = dataset.itemCount(); for (var i = 0; i < itemCount; i++) { var v = dataset.valueByIndex(i); if (v) { if (min) { min = Math.min(min, v); } else { min = v; } } } return min; }; // returns the maximum value for the specified dataset orsoncharts.KeyedValuesDataset.prototype.maxForDataset = function(dataset) { var max = null; var itemCount = dataset.itemCount(); for (var i = 0; i < itemCount; i++) { var v = dataset.valueByIndex(i); if (v) { if (max) { max = Math.max(max, v); } else { max = v; } } } return max; }; // returns the total of all values in this dataset (ignoring null values) orsoncharts.KeyedValuesDataset.prototype.total = function() { return this.totalForDataset(this); }; // returns the minimum value in this dataset (ignoring null values) orsoncharts.KeyedValuesDataset.prototype.min = function() { return this.minForDataset(this); }; // returns the maximum value in this dataset (ignoring null values) orsoncharts.KeyedValuesDataset.prototype.max = function() { return this.maxForDataset(this); }; orson-charts-2.1.0/js/src/Utils.js000066400000000000000000000024451417331271500170060ustar00rootroot00000000000000/* * Copyright 2014-2022 by David Gilbert. */ var orsoncharts; if (!orsoncharts) orsoncharts = {}; orsoncharts.Utils = {}; orsoncharts.Utils.makeArrayOf = function(value, length) { var arr = [], i = length; while (i--) { arr[i] = value; } return arr; }; // returns the chart entity reference for this element orsoncharts.Utils.findChartRef = function(element) { var id = element.getAttribute("jfreesvg:ref"); var found = false; var current = element; while (!found) { current = current.parentNode; if (current != null) { id = current.getAttribute("jfreesvg:ref"); found = (id != null); } else { found = true; } } return id; } // find the chart id by finding the group that is written for the entire chart orsoncharts.Utils.findChartId = function(element) { var id = null; var found = false; var current = element; while (!found) { current = current.parentNode; if (current != null) { var ref = current.getAttribute("jfreesvg:ref"); if (ref == 'ORSON_CHART_TOP_LEVEL') { found = true; id = current.getAttribute("id"); } } else { found = true; } } return id; } orson-charts-2.1.0/js/src/XYZDataset.js000066400000000000000000000074271417331271500177130ustar00rootroot00000000000000/* * Copyright 2014-2022 by David Gilbert and KNIME AG */ "use strict"; orsoncharts = orsoncharts ? orsoncharts : {}; /** * Constructor for a new XYZDataset * @constructor */ orsoncharts.XYZDataset = function() { this.data = { "series": [], "selections": []}; this.listeners = []; }; // returns the number of series in the dataset orsoncharts.XYZDataset.prototype.seriesCount = function() { return this.data.series.length; }; // returns an array of all series keys in the dataset orsoncharts.XYZDataset.prototype.seriesKeys = function() { return this.data.series.map(function(d) { return d[0]; }); }; // returns the key for the series with the specified index orsoncharts.XYZDataset.prototype.seriesKey = function(seriesIndex) { return this.data.series[seriesIndex][0]; }; // returns the index for the series with the specified key, or -1 orsoncharts.XYZDataset.prototype.seriesIndex = function(seriesKey) { if (!(typeof seriesKey === 'string')) throw new Error("The 'seriesKey' must be a string."); var seriesArray = this.data.series; var seriesCount = this.data.series.length; for (var s = 0; s < seriesCount; s++) { if (seriesArray[s][0] === seriesKey) { return s; } } return -1; }; // returns the number of items in the specified series orsoncharts.XYZDataset.prototype.itemCount = function(seriesIndex) { return this.data.series[seriesIndex][1].length; }; // returns the x-value for the specified item in a series orsoncharts.XYZDataset.prototype.x = function(seriesIndex, itemIndex) { return this.data.series[seriesIndex][1][itemIndex][0]; }; // returns the y-value for the specified item in a series orsoncharts.XYZDataset.prototype.y = function(seriesIndex, itemIndex) { return this.data.series[seriesIndex][1][itemIndex][1]; }; // returns the z-value for the specified item in a series orsoncharts.XYZDataset.prototype.z = function(seriesIndex, itemIndex) { return this.data.series[seriesIndex][1][itemIndex][2]; }; // returns an array [x, y, z] for the specified item in a series orsoncharts.XYZDataset.prototype.item = function(seriesIndex, itemIndex) { return this.data.series[seriesIndex][1][itemIndex]; }; // adds a data value (x, y) to the specified series (if the series does not // already exist in the dataset it is created orsoncharts.XYZDataset.prototype.add = function(seriesKey, x, y, z) { if (!(typeof seriesKey === 'string')) throw new Error("The 'seriesKey' must be a string."); var s = this.seriesIndex(seriesKey); if (s < 0) this.addSeries(seriesKey); var series = this.data.series; series[series.length-1][1].push([x, y, z]); }; // adds a new empty series with the specified key (which must be a string). orsoncharts.XYZDataset.prototype.addSeries = function(seriesKey) { if (!(typeof seriesKey === 'string')) throw new Error("The 'seriesKey' must be a string."); var s = this.seriesIndex(seriesKey); if (s >= 0) throw new Error("There is already a series with the key '" + seriesKey); this.data["series"].push([seriesKey, []]); }; // removeSeries orsoncharts.XYZDataset.prototype.removeSeries = function(seriesKey) { if (!(typeof seriesKey === 'string')) throw new Error("The 'seriesKey' must be a string."); var s = this.seriesIndex(seriesKey); if (s >= 0) { this.data["series"].splice(s, 1); } }; // Adds a listener to the dataset (the listener method will be called whenever // the dataset is modified) orsoncharts.XYZDataset.prototype.addListener = function(listenerMethod) { this.listeners.push(listenerMethod); }; // Deregisters the specified listener so that it no longer receives // notification of dataset changes orsoncharts.XYZDataset.prototype.removeListener = function(listenerMethod) { var i = this.listeners.indexOf(listenerMethod); if (i >= 0) { this.listeners.splice(i, 1); } }; orson-charts-2.1.0/js/src/XYZLabels.js000066400000000000000000000021141417331271500175140ustar00rootroot00000000000000/* * Orson Charts * ------------ * Copyright 2014-2022 by David Gilbert. */ "use strict"; if (!orsoncharts) orsoncharts = {}; /** * Constructor for a new XYZLabels instance * @constructor */ orsoncharts.XYZLabels = function() { if (!(this instanceof orsoncharts.XYZLabels)) { return new orsoncharts.XYZLabels(); } this.format = "{X}, {Y}, {Z} / {S}"; this.xDP = 2; this.yDP = 2; this.zDP = 2; }; // Generates a label for an item in a XYZDataset. orsoncharts.XYZLabels.prototype.itemLabel = function(dataset, seriesKey, itemIndex) { var labelStr = new String(this.format); var seriesKeyStr = seriesKey; var seriesIndex = dataset.seriesIndex(seriesKey); var item = dataset.item(seriesIndex, itemIndex); var xStr = item[0].toFixed(this.xDP); var yStr = item[1].toFixed(this.yDP); var zStr = item[2].toFixed(this.zDP); labelStr = labelStr.replace(/{X}/g, xStr); labelStr = labelStr.replace(/{Y}/g, yStr); labelStr = labelStr.replace(/{Z}/g, zStr); labelStr = labelStr.replace(/{S}/g, seriesKeyStr); return labelStr; }; orson-charts-2.1.0/pom.xml000066400000000000000000000171531417331271500154640ustar00rootroot00000000000000 4.0.0 Orson Charts Orson Charts is a 3D chart library for the Java platform. https://github.com/orson-charts org.jfree org.jfree.chart3d 2.1.0 jar David Gilbert dave@jfree.org GNU General Public License (GPL) http://www.gnu.org/licenses/gpl.txt repo https://github.com/jfree/orson-charts/issues GitHub Issues scm:git:git:https://github.com/jfree/orson-charts.git https://github.com/jfree/orson-charts UTF-8 11 11 org.junit.jupiter junit-jupiter-api 5.7.2 test org.junit.jupiter junit-jupiter-engine 5.7.2 test org.apache.maven.plugins maven-clean-plugin 3.1.0 org.apache.maven.plugins maven-resources-plugin 3.2.0 ${project.build.sourceEncoding} org.apache.maven.plugins maven-compiler-plugin 3.8.1 ${project.source.level} ${project.target.level} ${project.build.sourceEncoding} true org.apache.maven.plugins maven-javadoc-plugin 3.3.1 true true -Xdoclint:none attach-javadoc jar org.apache.maven.plugins maven-jar-plugin 3.2.0 maven-surefire-plugin 2.22.2 maven-failsafe-plugin 2.22.2 org.apache.maven.plugins maven-install-plugin 3.0.0-M1 ossrh https://oss.sonatype.org/content/repositories/snapshots release org.apache.maven.plugins maven-gpg-plugin 1.5 sign-artifacts verify sign org.sonatype.plugins nexus-staging-maven-plugin 1.6.7 true ossrh https://oss.sonatype.org/ false true org.apache.maven.plugins maven-javadoc-plugin 3.3.1 ${basedir}/src/main/java/overview.html true -Xdoclint:none attach-javadoc jar org.apache.maven.plugins maven-source-plugin 2.2.1 attach-sources jar-no-fork orson-charts-2.1.0/src/000077500000000000000000000000001417331271500147275ustar00rootroot00000000000000orson-charts-2.1.0/src/main/000077500000000000000000000000001417331271500156535ustar00rootroot00000000000000orson-charts-2.1.0/src/main/java/000077500000000000000000000000001417331271500165745ustar00rootroot00000000000000orson-charts-2.1.0/src/main/java/module-info.java000066400000000000000000000114761417331271500216660ustar00rootroot00000000000000/** * Orson Charts is a chart library for the Java(tm) platform (module name * {@code org.jfree.chart3d}) that can generate a wide variety of 3D charts for * use in client-side applications (JavaFX and Swing) and server-side * applications (with export to SVG, PDF, PNG and JPEG formats). Key features * include: *
    *
  1. multiple chart types: pie charts, bar charts (regular and * stacked), line charts, area charts, scatter plots and surface charts;
  2. *
  3. a built-in lightweight 3D rendering engine - no additional or complex * dependencies, resulting in easy deployment;
  4. *
  5. mouse-enabled chart viewing components (for both JavaFX and Swing) * provide 360 degree rotation and zooming for precise end-user view * control;
  6. *
  7. auto-adaptive axis labeling;
  8. *
  9. easy export of charts to PDF and SVG for reporting;
  10. *
  11. a clean and well-documented API, with a high degree of chart * configurability;
  12. *
* * * * * * * * * * *
* BarChart3DDemo1.svg * * ScatterPlot3DDemo2.svg *
* PieChart3DDemo1.svg * * AreaChart3DDemo1.svg *
Samples
*

* Orson Charts includes only 3D charts, for 2D charts we recommend the excellent * JFreeChart library * (by the same author). *

* There is also a version of Orson Charts available for the Android platform. *

* Getting Started *
* To get started with Orson Charts, you simply need to add the * org.jfree.chart3d module to your application and begin coding. * Your first step is to set up some data that you want to display. Orson Charts * reads data through a dataset interface - there are three key interfaces, one * that is used for pie charts (PieDataset3D), one that is used for * bar charts and other category based charts (CategoryDataset3D) * and one for plots that use numerical data (XYZDataset). There * are standard implementations of these interfaces includes in the library, * making it straightforward to create a new dataset. Here is an example for a * pie chart: *

*   StandardPieDataset3D dataset = new StandardPieDataset3D();
*   dataset.add("Milk Products", 625);
*   dataset.add("Meat", 114); *

* Once your dataset is ready, the next step is to create a chart object - here the * Chart3DFactory class can help, as it has utility methods to create * some standard chart types: *

*   Chart3D chart = Chart3DFactory.createPieChart("Title", "Subtitle", dataset); *

* Finally, if you are developing a Swing application, you will want to place the * chart somewhere in your UI. Here the Chart3DPanel class can * be used: *

*   Chart3DPanel chartPanel = new Chart3DPanel(chart); *

* You can find complete examples in the JFree Demos project at GitHub. * You are encouraged to explore these example programs and review these Javadoc * pages to learn more about Orson Charts. *

* More Information *
* Please visit * http://www.object-refinery.com/orsoncharts/index.html for the latest * information about Orson Charts. */ module org.jfree.chart3d { requires java.base; requires java.desktop; requires java.logging; exports org.jfree.chart3d; exports org.jfree.chart3d.axis; exports org.jfree.chart3d.data; exports org.jfree.chart3d.data.category; exports org.jfree.chart3d.data.function; exports org.jfree.chart3d.data.xyz; exports org.jfree.chart3d.export; exports org.jfree.chart3d.graphics2d; exports org.jfree.chart3d.graphics3d; exports org.jfree.chart3d.graphics3d.swing; exports org.jfree.chart3d.interaction; exports org.jfree.chart3d.label; exports org.jfree.chart3d.legend; exports org.jfree.chart3d.marker; exports org.jfree.chart3d.plot; exports org.jfree.chart3d.renderer; exports org.jfree.chart3d.renderer.category; exports org.jfree.chart3d.renderer.xyz; exports org.jfree.chart3d.style; exports org.jfree.chart3d.table; } orson-charts-2.1.0/src/main/java/org/000077500000000000000000000000001417331271500173635ustar00rootroot00000000000000orson-charts-2.1.0/src/main/java/org/jfree/000077500000000000000000000000001417331271500204565ustar00rootroot00000000000000orson-charts-2.1.0/src/main/java/org/jfree/chart3d/000077500000000000000000000000001417331271500220065ustar00rootroot00000000000000orson-charts-2.1.0/src/main/java/org/jfree/chart3d/Chart3D.java000066400000000000000000002267101417331271500241110ustar00rootroot00000000000000/* =========================================================== * Orson Charts : a 3D chart library for the Java(tm) platform * =========================================================== * * (C)opyright 2013-2022, by David Gilbert. All rights reserved. * * https://github.com/jfree/orson-charts * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . * * [Oracle and Java are registered trademarks of Oracle and/or its affiliates. * Other names may be trademarks of their respective owners.] * * If you do not wish to be bound by the terms of the GPL, an alternative * commercial license can be purchased. For details, please see visit the * Orson Charts home page: * * http://www.object-refinery.com/orsoncharts/index.html * */ package org.jfree.chart3d; import java.awt.BasicStroke; import java.awt.Stroke; import java.awt.geom.Line2D; import java.awt.Color; import java.awt.Graphics2D; import java.awt.Font; import java.awt.Paint; import java.awt.RenderingHints; import java.awt.Shape; import java.awt.geom.AffineTransform; import java.awt.geom.Path2D; import java.awt.geom.Point2D; import java.awt.geom.Dimension2D; import java.awt.geom.Rectangle2D; import java.io.Serializable; import java.io.IOException; import java.io.ObjectInputStream; import java.util.ArrayList; import java.util.Collections; import java.util.List; import java.util.HashMap; import java.util.Map; import javax.swing.event.EventListenerList; import org.jfree.chart3d.graphics3d.internal.FaceSorter; import org.jfree.chart3d.graphics3d.internal.StandardFaceSorter; import org.jfree.chart3d.graphics3d.internal.Utils2D; import org.jfree.chart3d.internal.ChartBox3D; import org.jfree.chart3d.internal.ChartBox3D.ChartBoxFace; import org.jfree.chart3d.internal.OnDrawHandler; import org.jfree.chart3d.internal.Args; import org.jfree.chart3d.internal.ObjectUtils; import org.jfree.chart3d.internal.TextUtils; import org.jfree.chart3d.axis.Axis3D; import org.jfree.chart3d.axis.TickData; import org.jfree.chart3d.axis.ValueAxis3D; import org.jfree.chart3d.data.ItemKey; import org.jfree.chart3d.graphics2d.Anchor2D; import org.jfree.chart3d.graphics2d.RefPt2D; import org.jfree.chart3d.graphics2d.TextAnchor; import org.jfree.chart3d.graphics3d.Dimension3D; import org.jfree.chart3d.graphics3d.DoubleSidedFace; import org.jfree.chart3d.graphics3d.Drawable3D; import org.jfree.chart3d.graphics3d.Face; import org.jfree.chart3d.graphics3d.LabelFace; import org.jfree.chart3d.graphics3d.Object3D; import org.jfree.chart3d.graphics3d.Offset2D; import org.jfree.chart3d.graphics3d.Point3D; import org.jfree.chart3d.graphics3d.RenderedElement; import org.jfree.chart3d.graphics3d.RenderingInfo; import org.jfree.chart3d.graphics3d.ViewPoint3D; import org.jfree.chart3d.graphics3d.World; import org.jfree.chart3d.interaction.InteractiveElementType; import org.jfree.chart3d.legend.LegendAnchor; import org.jfree.chart3d.legend.LegendBuilder; import org.jfree.chart3d.legend.StandardLegendBuilder; import org.jfree.chart3d.marker.Marker; import org.jfree.chart3d.marker.MarkerData; import org.jfree.chart3d.plot.CategoryPlot3D; import org.jfree.chart3d.plot.PiePlot3D; import org.jfree.chart3d.plot.Plot3D; import org.jfree.chart3d.plot.Plot3DChangeEvent; import org.jfree.chart3d.plot.Plot3DChangeListener; import org.jfree.chart3d.plot.XYZPlot; import org.jfree.chart3d.style.ChartStyle; import org.jfree.chart3d.style.ChartStyleChangeEvent; import org.jfree.chart3d.style.ChartStyleChangeListener; import org.jfree.chart3d.style.ChartStyler; import org.jfree.chart3d.table.GradientRectanglePainter; import org.jfree.chart3d.table.RectanglePainter; import org.jfree.chart3d.table.StandardRectanglePainter; import org.jfree.chart3d.table.TableElement; import org.jfree.chart3d.table.TextElement; /** * A chart object for 3D charts (this is the umbrella object that manages all * the components of the chart). The {@link Chart3DFactory} class provides * some factory methods to construct common types of charts. *

* All rendering is done via the Java2D API, so this object is able to draw to * any implementation of the Graphics2D API (including * JFreeSVG for * SVG output, and * OrsonPDF * for PDF output). *

* In the step prior to rendering, a chart is composed in a 3D model that is * referred to as the "world". The dimensions of this 3D model are measured * in "world units" and the overall size is controlled by the plot. You will * see some attributes in the API that are specified in "world units", and these * can be used to modify how objects are composed within the 3D world model. * Once the objects (for example, bars in a bar chart) within the world have * been composed, they are projected onto a 2D plane and rendered to the * {@code Graphics2D} target (such as the screen, image, SVG file or * PDF file). *

* Charts can have simple titles or composite titles (anything that can be * constructed as a {@link TableElement} instance. The {@link TitleUtils} * class contains methods to create a common title/subtitle composite title. * This is illustrated in some of the demo applications. The chart title * and legend (and also the axis labels) are not part of the 3D world model, * they are overlaid on the output after the 3D components have been * rendered. *

* NOTE: This class is serializable, but the serialization format is subject * to change in future releases and should not be relied upon for persisting * instances of this class. * * @see Chart3DFactory * @see Chart3DPanel */ @SuppressWarnings("serial") public class Chart3D implements Drawable3D, ChartElement, Plot3DChangeListener, ChartStyleChangeListener, Serializable { /** * The default projection distance. * * @since 1.2 */ public static final double DEFAULT_PROJ_DIST = 1500.0; /** * The key for a property that stores the interactive element type. * * @since 1.3 */ public static final String INTERACTIVE_ELEMENT_TYPE = "interactive_element_type"; /** * The key for a property that stores the series key. This is used to * store the series key on the {@link TableElement} representing a legend * item, and also on a corresponding {@link RenderedElement} after * chart rendering (in the {@link RenderingInfo}). * * @since 1.3 */ public static final String SERIES_KEY = "series_key"; /** The chart id. */ private String id; /** A background rectangle painter, if any. */ private RectanglePainter background; /** The chart title (can be {@code null}). */ private TableElement title; /** The anchor point for the title (never {@code null}). */ private Anchor2D titleAnchor; /** A builder for the chart legend (can be {@code null}). */ private LegendBuilder legendBuilder; /** The anchor point for the legend (never {@code null}). */ private Anchor2D legendAnchor; /** The orientation for the legend (never {@code null}). */ private Orientation legendOrientation; /** The plot. */ private Plot3D plot; /** The view point. */ private ViewPoint3D viewPoint; /** The projection distance. */ private double projDist; /** The chart box color (never {@code null}). */ private Color chartBoxColor; /** * A translation factor applied to the chart when drawing. We use this * to allow the user (optionally) to drag the chart from its center * location to better align it with the chart title and legend. */ private Offset2D translate2D; /** Storage for registered change listeners. */ private transient EventListenerList listenerList; /** * A flag that controls whether or not the chart will notify listeners * of changes (defaults to {@code true}, but sometimes it is useful * to disable this). */ private boolean notify; /** * Rendering hints that will be used for chart drawing. This can be * empty but it should never be {@code null}. * * @since 1.1 */ private transient RenderingHints renderingHints; /** * The chart style. * * @since 1.2 */ private ChartStyle style; /** A 3D model of the world (represents the chart). */ private transient World world; /** An object that sorts faces for rendering (painter's algorithm). */ private FaceSorter faceSorter; /** * A flag that controls whether or not element hints are added to the * {@code Graphics2D} output. */ private boolean elementHinting; /** * Creates a 3D chart for the specified plot using the default chart * style. Note that a plot instance must be used in one chart instance * only. * * @param title the chart title ({@code null} permitted). * @param subtitle the chart subtitle ({@code null} permitted). * @param plot the plot ({@code null} not permitted). * * @see Chart3DFactory */ public Chart3D(String title, String subtitle, Plot3D plot) { this(title, subtitle, plot, Chart3DFactory.getDefaultChartStyle()); } /** * Creates a 3D chart for the specified plot using the supplied style. * * @param title the chart title ({@code null} permitted). * @param subtitle the chart subtitle ({@code null} permitted). * @param plot the plot ({@code null} not permitted). * @param style the chart style ({@code null} not permitted). * * @since 1.2 */ public Chart3D(String title, String subtitle, Plot3D plot, ChartStyle style) { Args.nullNotPermitted(plot, "plot"); Args.nullNotPermitted(style, "style"); plot.setChart(this); this.background = new StandardRectanglePainter(Color.WHITE); if (title != null) { this.title = TitleUtils.createTitle(title, subtitle); } this.titleAnchor = TitleAnchor.TOP_LEFT; this.legendBuilder = new StandardLegendBuilder(); this.legendAnchor = LegendAnchor.BOTTOM_RIGHT; this.legendOrientation = Orientation.HORIZONTAL; this.plot = plot; this.plot.addChangeListener(this); Dimension3D dim = this.plot.getDimensions(); float distance = (float) dim.getDiagonalLength() * 3.0f; this.viewPoint = ViewPoint3D.createAboveViewPoint(distance); this.projDist = DEFAULT_PROJ_DIST; this.chartBoxColor = new Color(255, 255, 255, 100); this.translate2D = new Offset2D(); this.faceSorter = new StandardFaceSorter(); this.renderingHints = new RenderingHints( RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON); this.renderingHints.put(RenderingHints.KEY_TEXT_ANTIALIASING, RenderingHints.VALUE_TEXT_ANTIALIAS_ON); this.elementHinting = false; this.notify = true; this.listenerList = new EventListenerList(); this.style = style; this.style.addChangeListener(this); receive(new ChartStyler(this.style)); } /** * Returns the chart id. * * @return The chart id (possibly {@code null}). * * @since 1.3 */ public String getID() { return this.id; } /** * Sets the chart id. * * @param id the id ({@code null} permitted). * * @since 1.3 */ public void setID(String id) { this.id = id; } /** * Returns the background painter (an object that is responsible for filling * the background area before charts are rendered). The default value * is an instance of {@link StandardRectanglePainter} that paints the * background white. * * @return The background painter (possibly {@code null}). * * @see #setBackground(org.jfree.chart3d.table.RectanglePainter) */ public RectanglePainter getBackground() { return this.background; } /** * Sets the background painter and sends a {@link Chart3DChangeEvent} to * all registered listeners. A background painter is used to fill in the * background of the chart before the 3D rendering takes place. To fill * the background with a color or image, you can use * {@link StandardRectanglePainter}. To fill the background with a * gradient paint, use {@link GradientRectanglePainter}. * * @param background the background painter ({@code null} permitted). * * @see #getBackground() */ public void setBackground(RectanglePainter background) { this.background = background; fireChangeEvent(); } /** * Returns the chart title. A {@link TableElement} is used for the title, * since it allows a lot of flexibility in the types of title that can * be displayed. * * @return The chart title (possibly {@code null}). */ public TableElement getTitle() { return this.title; } /** * Sets the chart title and sends a {@link Chart3DChangeEvent} to all * registered listeners. This is a convenience method that constructs * the required {@link TableElement} under-the-hood. * * @param title the title ({@code null} permitted). */ public void setTitle(String title) { if (title == null) { setTitle((TableElement) null); } else { setTitle(title, this.style.getTitleFont(), TitleUtils.DEFAULT_TITLE_COLOR); } } /** * Sets the chart title and sends a {@link Chart3DChangeEvent} to all * registered listeners. This is a convenience method that constructs * the required {@link TableElement} under-the-hood. * * @param title the title ({@code null} not permitted). * @param font the font ({@code null} not permitted). * @param color the foreground color ({@code null} not permitted). */ public void setTitle(String title, Font font, Color color) { // defer 'title' null check Args.nullNotPermitted(font, "font"); Args.nullNotPermitted(color, "color"); TextElement te = new TextElement(title); te.setTag("CHART_TITLE"); te.setFont(font); te.setColor(color); setTitle(te); } /** * Sets the chart title and sends a {@link Chart3DChangeEvent} to all * registered listeners. You can set the title to {@code null}, in * which case there will be no chart title. * * @param title the title ({@code null} permitted). */ public void setTitle(TableElement title) { this.title = title; fireChangeEvent(); } /** * Returns the title anchor. This controls the position of the title * in the chart area. * * @return The title anchor (never {@code null}). * * @see #setTitleAnchor(Anchor2D) */ public Anchor2D getTitleAnchor() { return this.titleAnchor; } /** * Sets the title anchor and sends a {@link Chart3DChangeEvent} to all * registered listeners. There is a {@link TitleAnchor} class providing * some useful default anchors. * * @param anchor the anchor ({@code null} not permitted). * * @see #getTitleAnchor() */ public void setTitleAnchor(Anchor2D anchor) { Args.nullNotPermitted(anchor, "anchor"); this.titleAnchor = anchor; fireChangeEvent(); } /** * Returns the plot, which manages the dataset, the axes (if any), the * renderer (if any) and other attributes related to plotting data. The * plot is specified via the constructor...there is no method to set a * new plot for the chart, instead you need to create a new chart instance. * * @return The plot (never {@code null}). */ public Plot3D getPlot() { return this.plot; } /** * Returns the chart box color (the chart box is the visible, open-sided * box inside which data is plotted for all charts except pie charts). * The default value is {@code Color.WHITE}. * * @return The chart box color (never {@code null}). * * @see #setChartBoxColor(java.awt.Color) */ public Color getChartBoxColor() { return this.chartBoxColor; } /** * Sets the chart box color and sends a {@link Chart3DChangeEvent} to all * registered listeners. Bear in mind that {@link PiePlot3D} does not * display a chart box, so this attribute will be ignored for pie charts. * * @param color the color ({@code null} not permitted). * * @see #getChartBoxColor() */ public void setChartBoxColor(Color color) { Args.nullNotPermitted(color, "color"); this.chartBoxColor = color; fireChangeEvent(); } /** * Returns the dimensions of the 3D object. * * @return The dimensions (never {@code null}). */ @Override public Dimension3D getDimensions() { return this.plot.getDimensions(); } /** * Returns the view point. * * @return The view point (never {@code null}). */ @Override public ViewPoint3D getViewPoint() { return this.viewPoint; } /** * Sets the view point. * * @param viewPoint the view point ({@code null} not permitted). */ @Override public void setViewPoint(ViewPoint3D viewPoint) { Args.nullNotPermitted(viewPoint, "viewPoint"); this.viewPoint = viewPoint; fireChangeEvent(); } /** * Returns the projection distance. The default value is * {@link #DEFAULT_PROJ_DIST}, higher numbers flatten out the perspective * and reduce distortion in the projected image. * * @return The projection distance. * * @since 1.2 */ @Override public double getProjDistance() { return this.projDist; } /** * Sets the projection distance and sends a change event to all registered * listeners. * * @param dist the distance. * * @since 1.2 */ @Override public void setProjDistance(double dist) { this.projDist = dist; fireChangeEvent(); } /** * Sets the offset in 2D-space for the rendering of the chart. The * default value is {@code (0, 0)} but the user can modify it via * ALT-mouse-drag in the chart panel, providing an easy way to get improved * chart alignment in the panels (especially prior to export to PNG, SVG or * PDF). * * @return The offset (never {@code null}). */ @Override public Offset2D getTranslate2D() { return this.translate2D; } /** * Sets the offset in 2D-space for the rendering of the chart and sends a * change event to all registered listeners. * * @param offset the new offset ({@code null} not permitted). */ @Override public void setTranslate2D(Offset2D offset) { Args.nullNotPermitted(offset, "offset"); this.translate2D = offset; fireChangeEvent(); } /** * Returns the legend builder. The default value is an instance of * {@link StandardLegendBuilder}. If the legend builder is {@code null}, * no legend will be displayed for the chart. * * @return The legend builder (possibly {@code null}). * * @see #setLegendBuilder(org.jfree.chart3d.legend.LegendBuilder) * @see #setLegendAnchor(Anchor2D) */ public LegendBuilder getLegendBuilder() { return this.legendBuilder; } /** * Sets the legend builder and sends a change event to all registered * listeners. When the legend builder is {@code null}, no legend * will be displayed on the chart. * * @param legendBuilder the legend builder ({@code null} permitted). * * @see #setLegendAnchor(Anchor2D) */ public void setLegendBuilder(LegendBuilder legendBuilder) { this.legendBuilder = legendBuilder; fireChangeEvent(); } /** * Returns the legend anchor. * * @return The legend anchor (never {@code null}). * * @see #setLegendAnchor(Anchor2D) */ public Anchor2D getLegendAnchor() { return this.legendAnchor; } /** * Sets the legend anchor and sends a {@link Chart3DChangeEvent} to all * registered listeners. There is a {@link LegendAnchor} class providing * some useful default anchors. * * @param anchor the anchor ({@code null} not permitted). * * @see #getLegendAnchor() */ public void setLegendAnchor(Anchor2D anchor) { Args.nullNotPermitted(anchor, "anchor"); this.legendAnchor = anchor; fireChangeEvent(); } /** * Returns the orientation for the legend. * * @return The orientation (never {@code null}). * * @since 1.1 */ public Orientation getLegendOrientation() { return this.legendOrientation; } /** * Sets the legend orientation and sends a {@link Chart3DChangeEvent} * to all registered listeners. * * @param orientation the orientation ({@code null} not permitted). * * @since 1.1 */ public void setLegendOrientation(Orientation orientation) { Args.nullNotPermitted(orientation, "orientation"); this.legendOrientation = orientation; fireChangeEvent(); } /** * Sets the legend position (both the anchor point and the orientation) and * sends a {@link Chart3DChangeEvent} to all registered listeners. * This is a convenience method that calls both the * {@link #setLegendAnchor(Anchor2D)} and * {@link #setLegendOrientation(Orientation)} * methods. * * @param anchor the anchor ({@code null} not permitted). * @param orientation the orientation ({@code null} not permitted). * * @since 1.1 */ public void setLegendPosition(Anchor2D anchor, Orientation orientation) { setNotify(false); setLegendAnchor(anchor); setLegendOrientation(orientation); setNotify(true); } /** * Returns the collection of rendering hints for the chart. * * @return The rendering hints for the chart (never {@code null}). * * @see #setRenderingHints(RenderingHints) * * @since 1.1 */ public RenderingHints getRenderingHints() { return this.renderingHints; } /** * Sets the rendering hints for the chart. These will be added (using the * {@code Graphics2D.addRenderingHints()} method) near the start of * the chart rendering. Note that calling this method will replace all * existing hints assigned to the chart. If you simply wish to add an * additional hint, you can use {@code getRenderingHints().put(key, value)}. * * @param hints the rendering hints ({@code null} not permitted). * * @see #getRenderingHints() * * @since 1.1 */ public void setRenderingHints(RenderingHints hints) { Args.nullNotPermitted(hints, "hints"); this.renderingHints = hints; fireChangeEvent(); } /** * Returns a flag that indicates whether or not anti-aliasing is used when * the chart is drawn. * * @return The flag. * * @see #setAntiAlias(boolean) * @since 1.1 */ public boolean getAntiAlias() { Object val = this.renderingHints.get(RenderingHints.KEY_ANTIALIASING); return RenderingHints.VALUE_ANTIALIAS_ON.equals(val); } /** * Sets a flag that indicates whether or not anti-aliasing is used when the * chart is drawn. *

* Anti-aliasing usually improves the appearance of charts, but is slower. * * @param flag the new value of the flag. * * @see #getAntiAlias() * @since 1.1 */ public void setAntiAlias(boolean flag) { if (flag) { this.renderingHints.put(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON); } else { this.renderingHints.put(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_OFF); } fireChangeEvent(); } /** * Returns the flag that controls whether or not element hints will be * added to the {@code Graphics2D} output when the chart is rendered. * The default value is {@code false}. * * @return A boolean. * * @since 1.3 */ public boolean getElementHinting() { return this.elementHinting; } /** * Sets the flag that controls whether or not element hints will be * added to the {@code Graphics2D} output when the chart is rendered * and sends a change event to all registered listeners. * * @param hinting the new flag value. * * @since 1.3 */ public void setElementHinting(boolean hinting) { this.elementHinting = hinting; fireChangeEvent(); } /** * Returns the chart style. * * @return The chart style (never {@code null}). * * @since 1.2 */ public ChartStyle getStyle() { return this.style; } /** * Sets (and applies) the specified chart style. * * @param style the chart style ({@code null} not permitted). * * @since 1.2 */ public void setStyle(ChartStyle style) { Args.nullNotPermitted(style, "style"); this.style.removeChangeListener(this); this.style = style; this.style.addChangeListener(this); setNotify(false); receive(new ChartStyler(this.style)); setNotify(true); } /** * Creates a world containing the chart and the supplied chart box. * * @param chartBox the chart box ({@code null} permitted). */ private World createWorld(ChartBox3D chartBox) { World result = new World(); Dimension3D dim = this.plot.getDimensions(); double w = dim.getWidth(); double h = dim.getHeight(); double d = dim.getDepth(); if (chartBox != null) { result.add("chartbox", chartBox.createObject3D()); } this.plot.compose(result, -w / 2, -h / 2, -d / 2); return result; } /** * Draws the chart to the specified output target. * * @param g2 the output target ({@code null} not permitted). * * @return Information about the items rendered. */ @Override public RenderingInfo draw(Graphics2D g2, Rectangle2D bounds) { beginElement(g2, this.id, "ORSON_CHART_TOP_LEVEL"); Shape savedClip = g2.getClip(); g2.clip(bounds); g2.addRenderingHints(this.renderingHints); g2.setStroke(new BasicStroke(1.5f, BasicStroke.CAP_ROUND, BasicStroke.JOIN_ROUND, 1f)); Dimension3D dim3D = this.plot.getDimensions(); double w = dim3D.getWidth(); double h = dim3D.getHeight(); double depth = dim3D.getDepth(); ChartBox3D chartBox = null; if (this.plot instanceof XYZPlot || this.plot instanceof CategoryPlot3D) { double[] tickUnits = findAxisTickUnits(g2, w, h, depth); chartBox = new ChartBox3D(w, h, depth, -w / 2, -h / 2, -depth / 2, this.chartBoxColor); chartBox.setXTicks(fetchXTickData(this.plot, tickUnits[0])); chartBox.setYTicks(fetchYTickData(this.plot, tickUnits[1])); chartBox.setZTicks(fetchZTickData(this.plot, tickUnits[2])); chartBox.setXMarkers(fetchXMarkerData(this.plot)); chartBox.setYMarkers(fetchYMarkerData(this.plot)); chartBox.setZMarkers(fetchZMarkerData(this.plot)); } if (this.world == null) { this.world = createWorld(chartBox); } else if (chartBox != null) { this.world.clear("chartbox"); this.world.add("chartbox", chartBox.createObject3D()); } if (this.background != null) { this.background.fill(g2, bounds); } AffineTransform saved = g2.getTransform(); double dx = bounds.getX() + bounds.getWidth() / 2.0 + this.translate2D.getDX(); double dy = bounds.getY() + bounds.getHeight() / 2.0 + this.translate2D.getDY(); g2.translate(dx, dy); Point3D[] eyePts = this.world.calculateEyeCoordinates(this.viewPoint); Point2D[] pts = this.world.calculateProjectedPoints(this.viewPoint, this.projDist); // sort faces by z-order List facesInPaintOrder = new ArrayList<>(world.getFaces()); facesInPaintOrder = this.faceSorter.sort(facesInPaintOrder, eyePts); Line2D line = null; Stroke stroke = new BasicStroke(1.0f); for (Face f : facesInPaintOrder) { // check for the special case where the face is just a line if (f.getVertexCount() == 2) { g2.setPaint(f.getColor()); if (line == null) { line = new Line2D.Float(); } int v0 = f.getVertexIndex(0); int v1 = f.getVertexIndex(1); line.setLine(pts[v0].getX(), pts[v0].getY(), pts[v1].getX(), pts[v1].getY()); g2.setStroke(stroke); g2.draw(line); continue; } boolean drawOutline = f.getOutline(); double[] plane = f.calculateNormal(eyePts); double inprod = plane[0] * world.getSunX() + plane[1] * world.getSunY() + plane[2] * world.getSunZ(); double shade = (inprod + 1) / 2.0; if (f instanceof DoubleSidedFace || Utils2D.area2(pts[f.getVertexIndex(0)], pts[f.getVertexIndex(1)], pts[f.getVertexIndex(2)]) > 0.0) { Color c = f.getColor(); Path2D p = f.createPath(pts); g2.setPaint(new Color((int) (c.getRed() * shade), (int) (c.getGreen() * shade), (int) (c.getBlue() * shade), c.getAlpha())); if (this.elementHinting) { beginElementGroup(f, g2); } g2.fill(p); if (drawOutline) { g2.draw(p); } if (this.elementHinting) { endElementGroup(f, g2); } if (f instanceof ChartBoxFace && (this.plot instanceof CategoryPlot3D || this.plot instanceof XYZPlot)) { Stroke savedStroke = g2.getStroke(); ChartBoxFace cbf = (ChartBoxFace) f; drawGridlines(g2, cbf, pts); drawMarkers(g2, cbf, pts); g2.setStroke(savedStroke); } } else if (f instanceof LabelFace) { LabelFace lf = (LabelFace) f; Path2D p = lf.createPath(pts); Rectangle2D lb = p.getBounds2D(); g2.setFont(lf.getFont()); g2.setColor(lf.getBackgroundColor()); Rectangle2D bb = TextUtils.calcAlignedStringBounds( lf.getLabel(), g2, (float) lb.getCenterX(), (float) lb.getCenterY(), TextAnchor.CENTER); g2.fill(bb); g2.setColor(lf.getTextColor()); Rectangle2D r = TextUtils.drawAlignedString(lf.getLabel(), g2, (float) lb.getCenterX(), (float) lb.getCenterY(), TextAnchor.CENTER); lf.getOwner().setProperty("labelBounds", r); } } RenderingInfo info = new RenderingInfo(facesInPaintOrder, pts, dx, dy); OnDrawHandler onDrawHandler = new OnDrawHandler(info, this.elementHinting); // handle labels on pie plots... if (this.plot instanceof PiePlot3D) { drawPieLabels(g2, w, h, depth, info); } // handle axis labelling on non-pie plots... if (this.plot instanceof XYZPlot || this.plot instanceof CategoryPlot3D) { drawAxes(g2, chartBox, pts, info); } g2.setTransform(saved); // generate and draw the legend... if (this.legendBuilder != null) { TableElement legend = this.legendBuilder.createLegend(this.plot, this.legendAnchor, this.legendOrientation, this.style); if (legend != null) { Dimension2D legendSize = legend.preferredSize(g2, bounds); Rectangle2D legendArea = calculateDrawArea(legendSize, this.legendAnchor, bounds); legend.draw(g2, legendArea, onDrawHandler); } } // draw the title... if (this.title != null) { Dimension2D titleSize = this.title.preferredSize(g2, bounds); Rectangle2D titleArea = calculateDrawArea(titleSize, this.titleAnchor, bounds); this.title.draw(g2, titleArea, onDrawHandler); } g2.setClip(savedClip); endElement(g2); return info; } private void beginElementGroup(Face face, Graphics2D g2) { Object3D owner = face.getOwner(); ItemKey itemKey = (ItemKey) owner.getProperty(Object3D.ITEM_KEY); if (itemKey != null) { Map m = new HashMap<>(); m.put("ref", itemKey.toJSONString()); g2.setRenderingHint(Chart3DHints.KEY_BEGIN_ELEMENT, m); } } private void endElementGroup(Face face, Graphics2D g2) { Object3D owner = face.getOwner(); ItemKey itemKey = (ItemKey) owner.getProperty(Object3D.ITEM_KEY); if (itemKey != null) { g2.setRenderingHint(Chart3DHints.KEY_END_ELEMENT, Boolean.TRUE); } } /** * An implementation method that fetches x-axis tick data from the plot, * assuming it is either a {@link CategoryPlot3D} or an {@link XYZPlot}. * On a category plot, the x-axis is the column axis (and the tickUnit is * ignored). * * @param plot the plot. * @param tickUnit the tick unit. * * @return A list of tick data instances representing the tick marks and * values along the x-axis. */ private List fetchXTickData(Plot3D plot, double tickUnit) { if (plot instanceof CategoryPlot3D) { CategoryPlot3D cp = (CategoryPlot3D) plot; return cp.getColumnAxis().generateTickDataForColumns( cp.getDataset()); } if (plot instanceof XYZPlot) { XYZPlot xp = (XYZPlot) plot; return xp.getXAxis().generateTickData(tickUnit); } return Collections.emptyList(); } /** * An implementation method that fetches y-axis tick data from the plot, * assuming it is either a {@link CategoryPlot3D} or an {@link XYZPlot}. * On a category plot, the y-axis is the value axis. * * @param plot the plot. * @param tickUnit the tick unit. * * @return A list of tick data instances representing the tick marks and * values along the y-axis. */ private List fetchYTickData(Plot3D plot, double tickUnit) { if (plot instanceof CategoryPlot3D) { CategoryPlot3D cp = (CategoryPlot3D) plot; return cp.getValueAxis().generateTickData(tickUnit); } if (plot instanceof XYZPlot) { XYZPlot xp = (XYZPlot) plot; return xp.getYAxis().generateTickData(tickUnit); } return Collections.emptyList(); } /** * An implementation method that fetches z-axis tick data from the plot, * assuming it is either a {@link CategoryPlot3D} or an {@link XYZPlot}. * On a category plot, the z-axis is the row axis (and the tickUnit is * ignored). * * @param plot the plot. * @param tickUnit the tick unit. * * @return A list of tick data instances representing the tick marks and * values along the y-axis. */ private List fetchZTickData(Plot3D plot, double tickUnit) { if (plot instanceof CategoryPlot3D) { CategoryPlot3D cp = (CategoryPlot3D) plot; return cp.getRowAxis().generateTickDataForRows(cp.getDataset()); } if (plot instanceof XYZPlot) { XYZPlot xp = (XYZPlot) plot; return xp.getZAxis().generateTickData(tickUnit); } return Collections.emptyList(); } /** * Fetches marker data for the plot's x-axis. * * @param plot the plot ({@code null} not permitted). * * @return A list of marker data items (possibly empty but never * {@code null}). */ private List fetchXMarkerData(Plot3D plot) { if (plot instanceof CategoryPlot3D) { return ((CategoryPlot3D) plot).getColumnAxis().generateMarkerData(); } if (plot instanceof XYZPlot) { return ((XYZPlot) plot).getXAxis().generateMarkerData(); } return new ArrayList<>(0); } /** * Fetches marker data for the plot's x-axis. * * @param plot the plot ({@code null} not permitted). * * @return A list of marker data items (possibly empty but never * {@code null}). */ private List fetchYMarkerData(Plot3D plot) { if (plot instanceof CategoryPlot3D) { return ((CategoryPlot3D) plot).getValueAxis().generateMarkerData(); } if (plot instanceof XYZPlot) { return ((XYZPlot) plot).getYAxis().generateMarkerData(); } return new ArrayList<>(0); } /** * Fetches marker data for the plot's x-axis. * * @param plot the plot ({@code null} not permitted). * * @return A list of marker data items (possibly empty but never * {@code null}). */ private List fetchZMarkerData(Plot3D plot) { if (plot instanceof CategoryPlot3D) { return ((CategoryPlot3D) plot).getRowAxis().generateMarkerData(); } if (plot instanceof XYZPlot) { return ((XYZPlot) plot).getZAxis().generateMarkerData(); } return new ArrayList<>(0); } /** * Draw the gridlines for one chart box face. * * @param g2 the graphics target. * @param face the face. * @param pts the projection points. */ private void drawGridlines(Graphics2D g2, ChartBoxFace face, Point2D[] pts) { if (isGridlinesVisibleForX(this.plot)) { g2.setPaint(fetchGridlinePaintX(this.plot)); g2.setStroke(fetchGridlineStrokeX(this.plot)); List xA = face.getXTicksA(); List xB = face.getXTicksB(); for (int i = 0; i < xA.size(); i++) { Line2D line = new Line2D.Double( pts[face.getOffset() + xA.get(i).getVertexIndex()], pts[face.getOffset() + xB.get(i).getVertexIndex()]); g2.draw(line); } } if (isGridlinesVisibleForY(this.plot)) { g2.setPaint(fetchGridlinePaintY(this.plot)); g2.setStroke(fetchGridlineStrokeY(this.plot)); List yA = face.getYTicksA(); List yB = face.getYTicksB(); for (int i = 0; i < yA.size(); i++) { Line2D line = new Line2D.Double( pts[face.getOffset() + yA.get(i).getVertexIndex()], pts[face.getOffset() + yB.get(i).getVertexIndex()]); g2.draw(line); } } if (isGridlinesVisibleForZ(this.plot)) { g2.setPaint(fetchGridlinePaintZ(this.plot)); g2.setStroke(fetchGridlineStrokeZ(this.plot)); List zA = face.getZTicksA(); List zB = face.getZTicksB(); for (int i = 0; i < zA.size(); i++) { Line2D line = new Line2D.Double( pts[face.getOffset() + zA.get(i).getVertexIndex()], pts[face.getOffset() + zB.get(i).getVertexIndex()]); g2.draw(line); } } } /** * Returns {@code true} if gridlines are visible for the x-axis * (column axis in the case of a {@link CategoryPlot3D}) and * {@code false} otherwise. For pie charts, this method will always * return {@code false}. * * @param plot the plot. * * @return A boolean. */ private boolean isGridlinesVisibleForX(Plot3D plot) { if (plot instanceof CategoryPlot3D) { CategoryPlot3D cp = (CategoryPlot3D) plot; return cp.getGridlinesVisibleForColumns(); } if (plot instanceof XYZPlot) { XYZPlot xp = (XYZPlot) plot; return xp.isGridlinesVisibleX(); } return false; } /** * Returns {@code true} if gridlines are visible for the y-axis * (value axis in the case of a {@link CategoryPlot3D}) and * {@code false} otherwise. * * @param plot the plot. * * @return A boolean. */ private boolean isGridlinesVisibleForY(Plot3D plot) { if (plot instanceof CategoryPlot3D) { CategoryPlot3D cp = (CategoryPlot3D) plot; return cp.getGridlinesVisibleForValues(); } if (plot instanceof XYZPlot) { XYZPlot xp = (XYZPlot) plot; return xp.isGridlinesVisibleY(); } return false; } /** * Returns {@code true} if gridlines are visible for the z-axis * (row axis in the case of a {@link CategoryPlot3D}) and * {@code false} otherwise. * * @param plot the plot. * * @return A boolean. */ private boolean isGridlinesVisibleForZ(Plot3D plot) { if (plot instanceof CategoryPlot3D) { CategoryPlot3D cp = (CategoryPlot3D) plot; return cp.getGridlinesVisibleForRows(); } if (plot instanceof XYZPlot) { XYZPlot xp = (XYZPlot) plot; return xp.isGridlinesVisibleZ(); } return false; } /** * Returns the paint used to draw gridlines on the x-axis (or column axis * in the case of {@link CategoryPlot3D}). * * @param plot the plot. * * @return The paint. */ private Paint fetchGridlinePaintX(Plot3D plot) { if (plot instanceof CategoryPlot3D) { CategoryPlot3D cp = (CategoryPlot3D) plot; return cp.getGridlinePaintForColumns(); } if (plot instanceof XYZPlot) { XYZPlot xp = (XYZPlot) plot; return xp.getGridlinePaintX(); } return null; } /** * Returns the paint used to draw gridlines on the y-axis (or value axis * in the case of {@link CategoryPlot3D}). * * @param plot the plot. * * @return The paint. */ private Paint fetchGridlinePaintY(Plot3D plot) { if (plot instanceof CategoryPlot3D) { CategoryPlot3D cp = (CategoryPlot3D) plot; return cp.getGridlinePaintForValues(); } if (plot instanceof XYZPlot) { XYZPlot xp = (XYZPlot) plot; return xp.getGridlinePaintY(); } return null; } /** * Returns the paint used to draw gridlines on the z-axis (or row axis * in the case of {@link CategoryPlot3D}). * * @param plot the plot. * * @return The paint. */ private Paint fetchGridlinePaintZ(Plot3D plot) { if (plot instanceof CategoryPlot3D) { CategoryPlot3D cp = (CategoryPlot3D) plot; return cp.getGridlinePaintForRows(); } if (plot instanceof XYZPlot) { XYZPlot xp = (XYZPlot) plot; return xp.getGridlinePaintZ(); } return null; } /** * Returns the stroke used to draw gridlines on the x-axis (or column axis * in the case of {@link CategoryPlot3D}). * * @param plot the plot. * * @return The stroke. */ private Stroke fetchGridlineStrokeX(Plot3D plot) { if (plot instanceof CategoryPlot3D) { CategoryPlot3D cp = (CategoryPlot3D) plot; return cp.getGridlineStrokeForColumns(); } if (plot instanceof XYZPlot) { XYZPlot xp = (XYZPlot) plot; return xp.getGridlineStrokeX(); } return null; } /** * Returns the stroke used to draw gridlines on the y-axis (or value axis * in the case of {@link CategoryPlot3D}). * * @param plot the plot. * * @return The stroke. */ private Stroke fetchGridlineStrokeY(Plot3D plot) { if (plot instanceof CategoryPlot3D) { CategoryPlot3D cp = (CategoryPlot3D) plot; return cp.getGridlineStrokeForValues(); } if (plot instanceof XYZPlot) { XYZPlot xp = (XYZPlot) plot; return xp.getGridlineStrokeY(); } return null; } /** * Returns the stroke used to draw gridlines on the z-axis (or row axis * in the case of {@link CategoryPlot3D}). * * @param plot the plot. * * @return The stroke. */ private Stroke fetchGridlineStrokeZ(Plot3D plot) { if (plot instanceof CategoryPlot3D) { CategoryPlot3D cp = (CategoryPlot3D) plot; return cp.getGridlineStrokeForRows(); } if (plot instanceof XYZPlot) { XYZPlot xp = (XYZPlot) plot; return xp.getGridlineStrokeZ(); } return null; } /** * Draws the pie labels for a {@link PiePlot3D} in 2D-space by creating a * temporary world with vertices at anchor points for the labels, then * projecting the points to 2D-space. * * @param g2 the graphics target. * @param w the width. * @param h the height. * @param depth the depth. * @param info the rendering info ({@code null} permitted). */ @SuppressWarnings("unchecked") private void drawPieLabels(Graphics2D g2, double w, double h, double depth, RenderingInfo info) { PiePlot3D p = (PiePlot3D) this.plot; World labelOverlay = new World(); List objs = p.getLabelFaces(-w / 2, -h / 2, -depth / 2); for (Object3D obj : objs) { labelOverlay.add(obj); } Point2D[] ppts = labelOverlay.calculateProjectedPoints( this.viewPoint, this.projDist); for (int i = 0; i < p.getDataset().getItemCount() * 2; i++) { if (p.getDataset().getValue(i / 2) == null) { continue; } Face f = labelOverlay.getFaces().get(i); if (Utils2D.area2(ppts[f.getVertexIndex(0)], ppts[f.getVertexIndex(1)], ppts[f.getVertexIndex(2)]) > 0) { Comparable key = p.getDataset().getKey(i / 2); g2.setColor(p.getSectionLabelColorSource().getColor(key)); g2.setFont(p.getSectionLabelFontSource().getFont(key)); Point2D pt = Utils2D.centerPoint(ppts[f.getVertexIndex(0)], ppts[f.getVertexIndex(1)], ppts[f.getVertexIndex(2)], ppts[f.getVertexIndex(3)]); String label = p.getSectionLabelGenerator().generateLabel( p.getDataset(), key); String ref = "{\"type\": \"sectionLabel\", \"key\": \"" + key.toString() + "\"}"; beginElementWithRef(g2, ref); Rectangle2D bounds = TextUtils.drawAlignedString(label, g2, (float) pt.getX(), (float) pt.getY(), TextAnchor.CENTER); endElement(g2); if (info != null) { RenderedElement pieLabelRE = new RenderedElement( InteractiveElementType.SECTION_LABEL, bounds); pieLabelRE.setProperty("key", key); info.addOffsetElement(pieLabelRE); } } } } private void beginElementWithRef(Graphics2D g2, String ref) { beginElement(g2, null, ref); } private void beginElement(Graphics2D g2, String id, String ref) { if (this.elementHinting) { Map m = new HashMap<>(); if (id != null) { m.put("id", id); } m.put("ref", ref); g2.setRenderingHint(Chart3DHints.KEY_BEGIN_ELEMENT, m); } } private void endElement(Graphics2D g2) { if (this.elementHinting) { g2.setRenderingHint(Chart3DHints.KEY_END_ELEMENT, Boolean.TRUE); } } /** * Determines appropriate tick units for the axes in the chart. * * @param g2 the graphics target. * @param w the width. * @param h the height. * @param depth the depth. * * @return The tick sizes. */ private double[] findAxisTickUnits(Graphics2D g2, double w, double h, double depth) { World tempWorld = new World(); ChartBox3D chartBox = new ChartBox3D(w, h, depth, -w / 2.0, -h / 2.0, -depth / 2.0, Color.WHITE); tempWorld.add(chartBox.createObject3D()); Point2D[] axisPts2D = tempWorld.calculateProjectedPoints( this.viewPoint, this.projDist); // vertices Point2D v0 = axisPts2D[0]; Point2D v1 = axisPts2D[1]; Point2D v2 = axisPts2D[2]; Point2D v3 = axisPts2D[3]; Point2D v4 = axisPts2D[4]; Point2D v5 = axisPts2D[5]; Point2D v6 = axisPts2D[6]; Point2D v7 = axisPts2D[7]; // faces boolean a = chartBox.faceA().isFrontFacing(axisPts2D); boolean b = chartBox.faceB().isFrontFacing(axisPts2D); boolean c = chartBox.faceC().isFrontFacing(axisPts2D); boolean d = chartBox.faceD().isFrontFacing(axisPts2D); boolean e = chartBox.faceE().isFrontFacing(axisPts2D); boolean f = chartBox.faceF().isFrontFacing(axisPts2D); double xtick = 0, ytick = 0, ztick = 0; Axis3D xAxis = null; ValueAxis3D yAxis = null; Axis3D zAxis = null; if (this.plot instanceof XYZPlot) { XYZPlot pp = (XYZPlot) this.plot; xAxis = pp.getXAxis(); yAxis = pp.getYAxis(); zAxis = pp.getZAxis(); } else if (this.plot instanceof CategoryPlot3D) { CategoryPlot3D pp = (CategoryPlot3D) this.plot; xAxis = pp.getColumnAxis(); yAxis = pp.getValueAxis(); zAxis = pp.getRowAxis(); } if (xAxis != null && yAxis != null && zAxis != null) { double ab = (count(a, b) == 1 ? v0.distance(v1) : 0.0); double bc = (count(b, c) == 1 ? v3.distance(v2) : 0.0); double cd = (count(c, d) == 1 ? v4.distance(v7) : 0.0); double da = (count(d, a) == 1 ? v5.distance(v6) : 0.0); double be = (count(b, e) == 1 ? v0.distance(v3) : 0.0); double bf = (count(b, f) == 1 ? v1.distance(v2) : 0.0); double df = (count(d, f) == 1 ? v6.distance(v7) : 0.0); double de = (count(d, e) == 1 ? v5.distance(v4) : 0.0); double ae = (count(a, e) == 1 ? v0.distance(v5) : 0.0); double af = (count(a, f) == 1 ? v1.distance(v6) : 0.0); double cf = (count(c, f) == 1 ? v2.distance(v7) : 0.0); double ce = (count(c, e) == 1 ? v3.distance(v4) : 0.0); if (count(a, b) == 1 && longest(ab, bc, cd, da)) { if (xAxis instanceof ValueAxis3D) { xtick = ((ValueAxis3D) xAxis).selectTick(g2, v0, v1, v7); } } if (count(b, c) == 1 && longest(bc, ab, cd, da)) { if (xAxis instanceof ValueAxis3D) { xtick = ((ValueAxis3D) xAxis).selectTick(g2, v3, v2, v6); } } if (count(c, d) == 1 && longest(cd, ab, bc, da)) { if (xAxis instanceof ValueAxis3D) { xtick = ((ValueAxis3D) xAxis).selectTick(g2, v4, v7, v1); } } if (count(d, a) == 1 && longest(da, ab, bc, cd)) { if (xAxis instanceof ValueAxis3D) { xtick = ((ValueAxis3D) xAxis).selectTick(g2, v5, v6, v3); } } if (count(b, e) == 1 && longest(be, bf, df, de)) { ytick = yAxis.selectTick(g2, v0, v3, v7); } if (count(b, f) == 1 && longest(bf, be, df, de)) { ytick = yAxis.selectTick(g2, v1, v2, v4); } if (count(d, f) == 1 && longest(df, be, bf, de)) { ytick = yAxis.selectTick(g2, v6, v7, v0); } if (count(d, e) == 1 && longest(de, be, bf, df)) { ytick = yAxis.selectTick(g2, v5, v4, v1); } if (count(a, e) == 1 && longest(ae, af, cf, ce)) { if (zAxis instanceof ValueAxis3D) { ztick = ((ValueAxis3D) zAxis).selectTick(g2, v0, v5, v2); } } if (count(a, f) == 1 && longest(af, ae, cf, ce)) { if (zAxis instanceof ValueAxis3D) { ztick = ((ValueAxis3D) zAxis).selectTick(g2, v1, v6, v3); } } if (count(c, f) == 1 && longest(cf, ae, af, ce)) { if (zAxis instanceof ValueAxis3D) { ztick = ((ValueAxis3D) zAxis).selectTick(g2, v2, v7, v5); } } if (count(c, e) == 1 && longest(ce, ae, af, cf)) { if (zAxis instanceof ValueAxis3D) { ztick = ((ValueAxis3D) zAxis).selectTick(g2, v3, v4, v6); } } } return new double[] { xtick, ytick, ztick }; } private void populateAnchorPoints(List tickData, Point2D[] pts) { for (TickData t : tickData) { t.setAnchorPt(pts[t.getVertexIndex()]); } } /** * Draws the axes for a chart. * * @param g2 the graphics target ({@code null} not permitted). * @param chartBox the chart box (this contains projected points for * the tick marks and labels) * @param pts the projected points. * @param info an object to be populated with rendering info, if it is * non-{@code null}. */ private void drawAxes(Graphics2D g2, ChartBox3D chartBox, Point2D[] pts, RenderingInfo info) { // vertices Point2D v0 = pts[0]; Point2D v1 = pts[1]; Point2D v2 = pts[2]; Point2D v3 = pts[3]; Point2D v4 = pts[4]; Point2D v5 = pts[5]; Point2D v6 = pts[6]; Point2D v7 = pts[7]; // faces boolean a = chartBox.faceA().isFrontFacing(pts); boolean b = chartBox.faceB().isFrontFacing(pts); boolean c = chartBox.faceC().isFrontFacing(pts); boolean d = chartBox.faceD().isFrontFacing(pts); boolean e = chartBox.faceE().isFrontFacing(pts); boolean f = chartBox.faceF().isFrontFacing(pts); Axis3D xAxis = null, yAxis = null, zAxis = null; if (this.plot instanceof XYZPlot) { XYZPlot pp = (XYZPlot) this.plot; xAxis = pp.getXAxis(); yAxis = pp.getYAxis(); zAxis = pp.getZAxis(); } else if (this.plot instanceof CategoryPlot3D) { CategoryPlot3D pp = (CategoryPlot3D) this.plot; xAxis = pp.getColumnAxis(); yAxis = pp.getValueAxis(); zAxis = pp.getRowAxis(); } if (xAxis != null && yAxis != null && zAxis != null) { double ab = (count(a, b) == 1 ? v0.distance(v1) : 0.0); double bc = (count(b, c) == 1 ? v3.distance(v2) : 0.0); double cd = (count(c, d) == 1 ? v4.distance(v7) : 0.0); double da = (count(d, a) == 1 ? v5.distance(v6) : 0.0); double be = (count(b, e) == 1 ? v0.distance(v3) : 0.0); double bf = (count(b, f) == 1 ? v1.distance(v2) : 0.0); double df = (count(d, f) == 1 ? v6.distance(v7) : 0.0); double de = (count(d, e) == 1 ? v5.distance(v4) : 0.0); double ae = (count(a, e) == 1 ? v0.distance(v5) : 0.0); double af = (count(a, f) == 1 ? v1.distance(v6) : 0.0); double cf = (count(c, f) == 1 ? v2.distance(v7) : 0.0); double ce = (count(c, e) == 1 ? v3.distance(v4) : 0.0); List ticks; if (count(a, b) == 1 && longest(ab, bc, cd, da)) { ticks = chartBox.faceA().getXTicksA(); populateAnchorPoints(ticks, pts); xAxis.draw(g2, v0, v1, v7, ticks, info, this.elementHinting); } if (count(b, c) == 1 && longest(bc, ab, cd, da)) { ticks = chartBox.faceB().getXTicksB(); populateAnchorPoints(ticks, pts); xAxis.draw(g2, v3, v2, v6, ticks, info, this.elementHinting); } if (count(c, d) == 1 && longest(cd, ab, bc, da)) { ticks = chartBox.faceC().getXTicksB(); populateAnchorPoints(ticks, pts); xAxis.draw(g2, v4, v7, v1, ticks, info, this.elementHinting); } if (count(d, a) == 1 && longest(da, ab, bc, cd)) { ticks = chartBox.faceA().getXTicksB(); populateAnchorPoints(ticks, pts); xAxis.draw(g2, v5, v6, v3, ticks, info, this.elementHinting); } if (count(b, e) == 1 && longest(be, bf, df, de)) { ticks = chartBox.faceB().getYTicksA(); populateAnchorPoints(ticks, pts); yAxis.draw(g2, v0, v3, v7, ticks, info, this.elementHinting); } if (count(b, f) == 1 && longest(bf, be, df, de)) { ticks = chartBox.faceB().getYTicksB(); populateAnchorPoints(ticks, pts); yAxis.draw(g2, v1, v2, v4, ticks, info, this.elementHinting); } if (count(d, f) == 1 && longest(df, be, bf, de)) { ticks = chartBox.faceD().getYTicksA(); populateAnchorPoints(ticks, pts); yAxis.draw(g2, v6, v7, v0, ticks, info, this.elementHinting); } if (count(d, e) == 1 && longest(de, be, bf, df)) { ticks = chartBox.faceD().getYTicksB(); populateAnchorPoints(ticks, pts); yAxis.draw(g2, v5, v4, v1, ticks, info, this.elementHinting); } if (count(a, e) == 1 && longest(ae, af, cf, ce)) { ticks = chartBox.faceA().getZTicksA(); populateAnchorPoints(ticks, pts); zAxis.draw(g2, v0, v5, v2, ticks, info, this.elementHinting); } if (count(a, f) == 1 && longest(af, ae, cf, ce)) { ticks = chartBox.faceA().getZTicksB(); populateAnchorPoints(ticks, pts); zAxis.draw(g2, v1, v6, v3, ticks, info, this.elementHinting); } if (count(c, f) == 1 && longest(cf, ae, af, ce)) { ticks = chartBox.faceC().getZTicksB(); populateAnchorPoints(ticks, pts); zAxis.draw(g2, v2, v7, v5, ticks, info, this.elementHinting); } if (count(c, e) == 1 && longest(ce, ae, af, cf)) { ticks = chartBox.faceC().getZTicksA(); populateAnchorPoints(ticks, pts); zAxis.draw(g2, v3, v4, v6, ticks, info, this.elementHinting); } } } /** * Draws the markers for one face on a chart box. The {@code pts} * array contains all the projected points for all the vertices in the * world...the chart box face references the required points by index. * * @param g2 the graphics target ({@code null} not permitted). * @param face the face of the chart box ({@code null} not permitted). * @param pts the projected points for the whole world. */ private void drawMarkers(Graphics2D g2, ChartBoxFace face, Point2D[] pts) { // x markers List xmarkers = face.getXMarkers(); for (MarkerData m : xmarkers) { m.updateProjection(pts); Marker marker = fetchXMarker(this.plot, m.getMarkerKey()); beginElementWithRef(g2, "{\"type\": \"xMarker\", \"key\": \"" + m.getMarkerKey() + "\"}"); marker.draw(g2, m, true); endElement(g2); } // y markers List ymarkers = face.getYMarkers(); for (MarkerData m : ymarkers) { m.updateProjection(pts); Marker marker = fetchYMarker(this.plot, m.getMarkerKey()); beginElementWithRef(g2, "{\"type\": \"yMarker\", \"key\": \"" + m.getMarkerKey() + "\"}"); marker.draw(g2, m, false); endElement(g2); } // z markers List zmarkers = face.getZMarkers(); for (MarkerData m : zmarkers) { m.updateProjection(pts); beginElementWithRef(g2, "{\"type\": \"zMarker\", \"key\": \"" + m.getMarkerKey() + "\"}"); Marker marker = fetchZMarker(this.plot, m.getMarkerKey()); marker.draw(g2, m, false); endElement(g2); } } /** * Returns the marker from the plot's x-axis that has the specified key, * or {@code null} if there is no marker with that key. * * @param plot the plot ({@code null} not permitted). * @param key the marker key ({@code null} not permitted). * * @return The marker (possibly {@code null}). */ private Marker fetchXMarker(Plot3D plot, String key) { if (plot instanceof CategoryPlot3D) { return ((CategoryPlot3D) plot).getColumnAxis().getMarker(key); } else if (plot instanceof XYZPlot) { return ((XYZPlot) plot).getXAxis().getMarker(key); } return null; } /** * Returns the marker from the plot's y-axis that has the specified key, * or {@code null} if there is no marker with that key. * * @param plot the plot ({@code null} not permitted). * @param key the marker key ({@code null} not permitted). * * @return The marker (possibly {@code null}). */ private Marker fetchYMarker(Plot3D plot, String key) { if (plot instanceof CategoryPlot3D) { return ((CategoryPlot3D) plot).getValueAxis().getMarker(key); } else if (plot instanceof XYZPlot) { return ((XYZPlot) plot).getYAxis().getMarker(key); } return null; } /** * Returns the marker from the plot's z-axis that has the specified key, * or {@code null} if there is no marker with that key. * * @param plot the plot ({@code null} not permitted). * @param key the marker key ({@code null} not permitted). * * @return The marker (possibly {@code null}). */ private Marker fetchZMarker(Plot3D plot, String key) { if (plot instanceof CategoryPlot3D) { return ((CategoryPlot3D) plot).getRowAxis().getMarker(key); } else if (plot instanceof XYZPlot) { return ((XYZPlot) plot).getZAxis().getMarker(key); } return null; } /** * Receives a visitor. The visitor is first directed to the plot, then * the visit is completed for the chart. * * @param visitor the visitor. * * @since 1.2 */ @Override public void receive(ChartElementVisitor visitor) { this.plot.receive(visitor); visitor.visit(this); } /** * Tests this chart for equality with an arbitrary object. * * @param obj the object ({@code null} not permitted). * * @return A boolean. */ @Override public boolean equals(Object obj) { if (obj == this) { return true; } if (!(obj instanceof Chart3D)) { return false; } Chart3D that = (Chart3D) obj; if (!ObjectUtils.equals(this.background, that.background)) { return false; } if (!ObjectUtils.equals(this.title, that.title)) { return false; } if (!this.titleAnchor.equals(that.titleAnchor)) { return false; } if (!ObjectUtils.equalsPaint(this.chartBoxColor, that.chartBoxColor)) { return false; } if (!ObjectUtils.equals(this.legendBuilder, that.legendBuilder)) { return false; } if (!this.legendAnchor.equals(that.legendAnchor)) { return false; } if (this.legendOrientation != that.legendOrientation) { return false; } if (!this.renderingHints.equals(that.renderingHints)) { return false; } if (this.projDist != that.projDist) { return false; } return true; } /** * A utility method that calculates a drawing area based on a bounding area * and an anchor. * * @param dim the dimensions for the drawing area ({@code null} not * permitted). * @param anchor the anchor ({@code null} not permitted). * @param bounds the bounds ({@code null} not permitted). * * @return A drawing area. */ private Rectangle2D calculateDrawArea(Dimension2D dim, Anchor2D anchor, Rectangle2D bounds) { Args.nullNotPermitted(dim, "dim"); Args.nullNotPermitted(anchor, "anchor"); Args.nullNotPermitted(bounds, "bounds"); double x, y; double w = Math.min(dim.getWidth(), bounds.getWidth()); double h = Math.min(dim.getHeight(), bounds.getHeight()); if (anchor.getRefPt().equals(RefPt2D.CENTER)) { x = bounds.getCenterX() - w / 2.0; y = bounds.getCenterY() - h / 2.0; } else if (anchor.getRefPt().equals(RefPt2D.CENTER_LEFT)) { x = bounds.getX() + anchor.getOffset().getDX(); y = bounds.getCenterY() - h / 2.0; } else if (anchor.getRefPt().equals(RefPt2D.CENTER_RIGHT)) { x = bounds.getMaxX() - anchor.getOffset().getDX() - dim.getWidth(); y = bounds.getCenterY() - h / 2.0; } else if (anchor.getRefPt().equals(RefPt2D.TOP_CENTER)) { x = bounds.getCenterX() - w / 2.0; y = bounds.getY() + anchor.getOffset().getDY(); } else if (anchor.getRefPt().equals(RefPt2D.TOP_LEFT)) { x = bounds.getX() + anchor.getOffset().getDX(); y = bounds.getY() + anchor.getOffset().getDY(); } else if (anchor.getRefPt().equals(RefPt2D.TOP_RIGHT)) { x = bounds.getMaxX() - anchor.getOffset().getDX() - dim.getWidth(); y = bounds.getY() + anchor.getOffset().getDY(); } else if (anchor.getRefPt().equals(RefPt2D.BOTTOM_CENTER)) { x = bounds.getCenterX() - w / 2.0; y = bounds.getMaxY() - anchor.getOffset().getDY() - dim.getHeight(); } else if (anchor.getRefPt().equals(RefPt2D.BOTTOM_RIGHT)) { x = bounds.getMaxX() - anchor.getOffset().getDX() - dim.getWidth(); y = bounds.getMaxY() - anchor.getOffset().getDY() - dim.getHeight(); } else if (anchor.getRefPt().equals(RefPt2D.BOTTOM_LEFT)) { x = bounds.getX() + anchor.getOffset().getDX(); y = bounds.getMaxY() - anchor.getOffset().getDY() - dim.getHeight(); } else { x = 0.0; y = 0.0; } return new Rectangle2D.Double(x, y, w, h); } /** * Returns {@code true} if x is the longest of the four lengths, * and {@code false} otherwise. * * @param x the x-length. * @param a length 1. * @param b length 2. * @param c length 3. * * @return A boolean. */ private boolean longest(double x, double a, double b, double c) { return x >= a && x >= b && x >= c; } /** * Returns the number (0, 1 or 2) arguments that have the value * {@code true}. We use this to examine the visibility of * adjacent walls of the chart box...where only one wall is visible, there * is an opportunity to display the axis along that edge. * * @param a boolean argument 1. * @param b boolean argument 2. * * @return 0, 1, or 2. */ private int count(boolean a, boolean b) { int result = 0; if (a) { result++; } if (b) { result++; } return result; } /** * Receives notification of a plot change event, refreshes the 3D model * (world) and passes the event on, wrapped in a {@link Chart3DChangeEvent}, * to all registered listeners. * * @param event the plot change event. */ @Override public void plotChanged(Plot3DChangeEvent event) { if (event.requiresWorldUpdate()) { this.world = null; } notifyListeners(new Chart3DChangeEvent(event, this)); } @Override public void styleChanged(ChartStyleChangeEvent event) { ChartStyler styler = new ChartStyler(event.getChartStyle()); receive(styler); // create a visitor that will visit all chart components and apply the // style notifyListeners(new Chart3DChangeEvent(event, this)); } /** * Registers a listener to receive notification of changes to the chart. * * @param listener the listener ({@code null} not permitted). */ public void addChangeListener(Chart3DChangeListener listener) { this.listenerList.add(Chart3DChangeListener.class, listener); } /** * Deregisters a listener so that it no longer receives notification of * changes to the chart. * * @param listener the listener ({@code null} not permitted). */ public void removeChangeListener(Chart3DChangeListener listener) { this.listenerList.remove(Chart3DChangeListener.class, listener); } /** * Notifies all registered listeners that the chart has been modified. * * @param event information about the change event. */ public void notifyListeners(Chart3DChangeEvent event) { // if the 'notify' flag has been switched to false, we don't notify // the listeners if (!this.notify) { return; } Object[] listeners = this.listenerList.getListenerList(); for (int i = listeners.length - 2; i >= 0; i -= 2) { if (listeners[i] == Chart3DChangeListener.class) { ((Chart3DChangeListener) listeners[i + 1]).chartChanged(event); } } } /** * Returns a flag that controls whether or not change events are sent to * registered listeners. * * @return A boolean. * * @see #setNotify(boolean) */ public boolean isNotify() { return this.notify; } /** * Sets a flag that controls whether or not listeners receive * {@link Chart3DChangeEvent} notifications. * * @param notify a boolean. * * @see #isNotify() */ public void setNotify(boolean notify) { this.notify = notify; // if the flag is being set to true, there may be queued up changes... if (notify) { this.world = null; fireChangeEvent(); } } /** * Sends a {@link Chart3DChangeEvent} to all registered listeners. */ protected void fireChangeEvent() { notifyListeners(new Chart3DChangeEvent(this, this)); } /** * Provides serialization support. * * @param stream the input stream. * * @throws IOException if there is an I/O error. * @throws ClassNotFoundException if there is a classpath problem. */ private void readObject(ObjectInputStream stream) throws IOException, ClassNotFoundException { stream.defaultReadObject(); // recreate an empty listener list this.listenerList = new EventListenerList(); this.plot.addChangeListener(this); // RenderingHints is not easily serialized, so we just put back the // defaults... this.renderingHints = new RenderingHints( RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON); this.renderingHints.put(RenderingHints.KEY_TEXT_ANTIALIASING, RenderingHints.VALUE_TEXT_ANTIALIAS_ON); } /** * Returns a string representing the {@code element}, primarily for * debugging purposes. * * @param element the element ({@code null} not permitted). * * @return A string (never {@code null}). */ public static String renderedElementToString(RenderedElement element) { Object type = element.getProperty(RenderedElement.TYPE); if (InteractiveElementType.SECTION_LABEL.equals(type)) { StringBuilder sb = new StringBuilder(); sb.append("Section label with key '"); Object key = element.getProperty("key"); sb.append(key.toString()); sb.append("'"); return sb.toString(); } else if (InteractiveElementType.LEGEND_ITEM.equals(type)) { StringBuilder sb = new StringBuilder(); sb.append("Legend item with section key '"); Object key = element.getProperty(Chart3D.SERIES_KEY); sb.append(key); sb.append("'"); return sb.toString(); } else if (InteractiveElementType.AXIS_LABEL.equals(type)) { return "Axis label with the label '" + element.getProperty("label") + "'"; } else if (InteractiveElementType.CATEGORY_AXIS_TICK_LABEL.equals(type)) { return "Axis tick label with the label '" + element.getProperty("label") + "'"; } else if (InteractiveElementType.VALUE_AXIS_TICK_LABEL.equals(type)) { return "Axis tick label with the value '" + element.getProperty("value") + "'"; } else if ("obj3d".equals(type)) { StringBuilder sb = new StringBuilder(); sb.append("An object in the 3D model"); ItemKey itemKey = (ItemKey) element.getProperty(Object3D.ITEM_KEY); if (itemKey != null) { sb.append(" representing the data item ["); sb.append(itemKey); sb.append("]"); } return sb.toString(); } else { return element.toString(); } } } orson-charts-2.1.0/src/main/java/org/jfree/chart3d/Chart3DChangeEvent.java000066400000000000000000000055231417331271500262160ustar00rootroot00000000000000/* =========================================================== * Orson Charts : a 3D chart library for the Java(tm) platform * =========================================================== * * (C)opyright 2013-2022, by David Gilbert. All rights reserved. * * https://github.com/jfree/orson-charts * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . * * [Oracle and Java are registered trademarks of Oracle and/or its affiliates. * Other names may be trademarks of their respective owners.] * * If you do not wish to be bound by the terms of the GPL, an alternative * commercial license can be purchased. For details, please see visit the * Orson Charts home page: * * http://www.object-refinery.com/orsoncharts/index.html * */ package org.jfree.chart3d; import java.util.EventObject; import org.jfree.chart3d.internal.Args; /** * An event indicating some change in the attributes of a chart. Typically * this indicates that the chart needs to be redrawn. Any object that * implements the {@link Chart3DChangeListener} interface can register * with a chart to receive change event notification. *

* NOTE: This class is serializable, but the serialization format is subject * to change in future releases and should not be relied upon for persisting * instances of this class. */ @SuppressWarnings("serial") public class Chart3DChangeEvent extends EventObject { /** The chart that is the source of the event. */ private Chart3D chart; /** * Creates a new event. * * @param chart the chart that is the source of the event ({@code null} * not permitted). */ public Chart3DChangeEvent(Chart3D chart) { this(chart, chart); } /** * Creates a new event. * * @param source the source. * @param chart the chart that is the source of the event ({@code null} * not permitted). */ public Chart3DChangeEvent(Object source, Chart3D chart) { super(source); Args.nullNotPermitted(chart, "chart"); this.chart = chart; } /** * Returns the chart that this event is associated with. * * @return The chart (never {@code null}). */ public Chart3D getChart() { return this.chart; } } orson-charts-2.1.0/src/main/java/org/jfree/chart3d/Chart3DChangeListener.java000066400000000000000000000036571417331271500267300ustar00rootroot00000000000000/* =========================================================== * Orson Charts : a 3D chart library for the Java(tm) platform * =========================================================== * * (C)opyright 2013-2022, by David Gilbert. All rights reserved. * * https://github.com/jfree/orson-charts * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . * * [Oracle and Java are registered trademarks of Oracle and/or its affiliates. * Other names may be trademarks of their respective owners.] * * If you do not wish to be bound by the terms of the GPL, an alternative * commercial license can be purchased. For details, please see visit the * Orson Charts home page: * * http://www.object-refinery.com/orsoncharts/index.html * */ package org.jfree.chart3d; import java.util.EventListener; /** * An interface for receiving notification of changes to a {@link Chart3D} * instance. *

* The {@link Chart3DPanel} class implements this interface so that it can * receive notification of changes to the chart being displayed in the * panel (whenever the chart changes, the panel is repainted). */ public interface Chart3DChangeListener extends EventListener { /** * Called to inform that a chart change event has occurred. * * @param event the event. */ void chartChanged(Chart3DChangeEvent event); } orson-charts-2.1.0/src/main/java/org/jfree/chart3d/Chart3DFactory.java000066400000000000000000000463211417331271500254370ustar00rootroot00000000000000/* =========================================================== * Orson Charts : a 3D chart library for the Java(tm) platform * =========================================================== * * (C)opyright 2013-2022, by David Gilbert. All rights reserved. * * https://github.com/jfree/orson-charts * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . * * [Oracle and Java are registered trademarks of Oracle and/or its affiliates. * Other names may be trademarks of their respective owners.] * * If you do not wish to be bound by the terms of the GPL, an alternative * commercial license can be purchased. For details, please see visit the * Orson Charts home page: * * http://www.object-refinery.com/orsoncharts/index.html * */ package org.jfree.chart3d; import org.jfree.chart3d.axis.CategoryAxis3D; import org.jfree.chart3d.axis.LabelOrientation; import org.jfree.chart3d.axis.NumberAxis3D; import org.jfree.chart3d.axis.StandardCategoryAxis3D; import org.jfree.chart3d.axis.ValueAxis3D; import org.jfree.chart3d.data.PieDataset3D; import org.jfree.chart3d.data.Range; import org.jfree.chart3d.data.category.CategoryDataset3D; import org.jfree.chart3d.data.function.Function3D; import org.jfree.chart3d.data.xyz.XYZDataset; import org.jfree.chart3d.data.xyz.XYZSeriesCollection; import org.jfree.chart3d.internal.Args; import org.jfree.chart3d.legend.ColorScaleLegendBuilder; import org.jfree.chart3d.plot.CategoryPlot3D; import org.jfree.chart3d.plot.PiePlot3D; import org.jfree.chart3d.plot.XYZPlot; import org.jfree.chart3d.renderer.category.AreaRenderer3D; import org.jfree.chart3d.renderer.category.BarRenderer3D; import org.jfree.chart3d.renderer.category.CategoryRenderer3D; import org.jfree.chart3d.renderer.category.LineRenderer3D; import org.jfree.chart3d.renderer.category.StackedBarRenderer3D; import org.jfree.chart3d.renderer.xyz.BarXYZRenderer; import org.jfree.chart3d.renderer.xyz.LineXYZRenderer; import org.jfree.chart3d.renderer.xyz.ScatterXYZRenderer; import org.jfree.chart3d.renderer.xyz.SurfaceRenderer; import org.jfree.chart3d.renderer.xyz.XYZRenderer; import org.jfree.chart3d.style.ChartStyle; import org.jfree.chart3d.style.StandardChartStyle; /** * Utility methods for constructing common chart types. Charts can be * assembled piece-wise, but usually it is simpler to use the methods in this * class then customise the resulting chart as necessary. */ public class Chart3DFactory { /** * Private constructor prevents instantiation which is unnecessary. */ private Chart3DFactory() { // no need to instantiate this ever } /** The chart style that will be used when creating a new chart. */ static ChartStyle defaultStyle = new StandardChartStyle(); /** * Returns a new instance of the default chart style (so that, by default, * all charts will have an independent style instance). * * @return The default chart style (never {@code null}). * * @since 1.2 */ public static ChartStyle getDefaultChartStyle() { return defaultStyle.clone(); } /** * Sets the style that will be used when creating new charts. * * @param style the style ({@code null} not permitted). * * @since 1.2 */ public static void setDefaultChartStyle(ChartStyle style) { Args.nullNotPermitted(style, "style"); defaultStyle = style.clone(); } /** * Creates and returns a pie chart based on the supplied dataset. The * chart returned by this method will be constructed using a * {@link PiePlot3D} instance (so it is safe to cast the result of * {@code chart.getPlot()}). *

* For reference, here is a sample pie chart: *

* PieChart3DDemo1.svg *
* * @param title the chart title ({@code null} permitted). * @param subtitle the chart subtitle ({@code null} permitted). * @param dataset the dataset ({@code null} not permitted). * * @return A pie chart (never {@code null}). */ public static Chart3D createPieChart(String title, String subtitle, PieDataset3D dataset) { PiePlot3D plot = new PiePlot3D(dataset); return new Chart3D(title, subtitle, plot); } /** * Creates and returns a bar chart based on the supplied dataset. The chart * returned by this method will be constructed with a * {@link CategoryPlot3D} using a {@link BarRenderer3D} (so it is * safe to cast the plot and/or renderer to customise attributes that are * specific to those subclasses). *

* For reference, here is a sample bar chart: *
* BarChart3DDemo1.svg *
* * @param title the chart title ({@code null} permitted). * @param subtitle the chart subtitle ({@code null} permitted). * @param dataset the dataset ({@code null} not permitted). * @param rowAxisLabel the row axis label ({@code null} permitted). * @param columnAxisLabel the column axis label ({@code null} * permitted). * @param valueAxisLabel the value axis label ({@code null} permitted). * * @return A bar chart (never {@code null}). */ public static Chart3D createBarChart(String title, String subtitle, CategoryDataset3D dataset, String rowAxisLabel, String columnAxisLabel, String valueAxisLabel) { StandardCategoryAxis3D rowAxis = new StandardCategoryAxis3D(rowAxisLabel); rowAxis.setTickLabelOrientation(LabelOrientation.PERPENDICULAR); CategoryAxis3D columnAxis = new StandardCategoryAxis3D(columnAxisLabel); NumberAxis3D valueAxis = new NumberAxis3D(valueAxisLabel, new Range(0.0, 1.0)); valueAxis.setTickLabelOrientation(LabelOrientation.PERPENDICULAR); CategoryRenderer3D renderer = new BarRenderer3D(); CategoryPlot3D plot = new CategoryPlot3D(dataset, renderer, rowAxis, columnAxis, valueAxis); return new Chart3D(title, subtitle, plot); } /** * Creates and returns a stacked bar chart based on the supplied dataset. * The chart returned by this method will be constructed with a * {@link CategoryPlot3D} using a {@link StackedBarRenderer3D} (so it is * safe to cast the plot and/or renderer to customise attributes that * are specific to those subclasses). *

* For reference, here is a sample stacked bar chart: *
* StackedBarChart3DDemo1.svg *
* * @param title the chart title ({@code null} permitted). * @param subtitle the chart subtitle ({@code null} permitted). * @param dataset the dataset ({@code null} not permitted). * @param rowAxisLabel the row axis label ({@code null} permitted). * @param columnAxisLabel the column axis label ({@code null} permitted). * @param valueAxisLabel the value axis label ({@code null} permitted). * * @return A stacked bar chart (never {@code null}). */ public static Chart3D createStackedBarChart(String title, String subtitle, CategoryDataset3D dataset, String rowAxisLabel, String columnAxisLabel, String valueAxisLabel) { StandardCategoryAxis3D rowAxis = new StandardCategoryAxis3D(rowAxisLabel); rowAxis.setTickLabelOrientation(LabelOrientation.PERPENDICULAR); CategoryAxis3D columnAxis = new StandardCategoryAxis3D(columnAxisLabel); NumberAxis3D valueAxis = new NumberAxis3D(valueAxisLabel, new Range(0.0, 1.0)); valueAxis.setTickLabelOrientation(LabelOrientation.PERPENDICULAR); CategoryRenderer3D renderer = new StackedBarRenderer3D(); CategoryPlot3D plot = new CategoryPlot3D(dataset, renderer, rowAxis, columnAxis, valueAxis); return new Chart3D(title, subtitle, plot); } /** * Creates and returns an area chart based on the supplied dataset. The * chart returned by this method will be constructed with a * {@link CategoryPlot3D} using an {@link AreaRenderer3D} (so it is safe * to cast the plot and/or renderer to customise attributes that are * specific to those subclasses). *

* For reference, here is a sample area chart: *
* AreaChart3DDemo1.svg *
* * @param title the chart title ({@code null} permitted). * @param subtitle the chart subtitle ({@code null} permitted). * @param dataset the dataset ({@code null} not permitted). * @param rowAxisLabel the row axis label ({@code null} permitted). * @param columnAxisLabel the column axis label ({@code null} permitted). * @param valueAxisLabel the value axis label ({@code null} permitted). * * @return An area chart (never {@code null}). */ public static Chart3D createAreaChart(String title, String subtitle, CategoryDataset3D dataset, String rowAxisLabel, String columnAxisLabel, String valueAxisLabel) { StandardCategoryAxis3D rowAxis = new StandardCategoryAxis3D(rowAxisLabel); rowAxis.setTickLabelOrientation(LabelOrientation.PERPENDICULAR); StandardCategoryAxis3D columnAxis = new StandardCategoryAxis3D( columnAxisLabel); columnAxis.setFirstCategoryHalfWidth(true); columnAxis.setLastCategoryHalfWidth(true); NumberAxis3D valueAxis = new NumberAxis3D(valueAxisLabel, new Range(0.0, 1.0)); valueAxis.setTickLabelOrientation(LabelOrientation.PERPENDICULAR); CategoryRenderer3D renderer = new AreaRenderer3D(); CategoryPlot3D plot = new CategoryPlot3D(dataset, renderer, rowAxis, columnAxis, valueAxis); return new Chart3D(title, subtitle, plot); } /** * Creates and returns a line chart based on the supplied dataset. The * chart returned by this method will be constructed with a * {@link CategoryPlot3D} using a {@link LineRenderer3D} (so it is safe * to cast the plot and/or renderer to customise attributes that are * specific to those subclasses). *

* For reference, here is a sample line chart: *
* LineChart3DDemo1.svg *
* * @param title the chart title ({@code null} permitted). * @param subtitle the chart subtitle ({@code null} permitted). * @param dataset the dataset ({@code null} not permitted). * @param rowAxisLabel the row axis label ({@code null} permitted). * @param columnAxisLabel the column axis label ({@code null} permitted). * @param valueAxisLabel the value axis label ({@code null} permitted). * * @return A line chart (never {@code null}). */ public static Chart3D createLineChart(String title, String subtitle, CategoryDataset3D dataset, String rowAxisLabel, String columnAxisLabel, String valueAxisLabel) { StandardCategoryAxis3D rowAxis = new StandardCategoryAxis3D(rowAxisLabel); rowAxis.setTickLabelOrientation(LabelOrientation.PERPENDICULAR); StandardCategoryAxis3D columnAxis = new StandardCategoryAxis3D(columnAxisLabel); columnAxis.setFirstCategoryHalfWidth(true); columnAxis.setLastCategoryHalfWidth(true); NumberAxis3D valueAxis = new NumberAxis3D(valueAxisLabel, new Range(0.0, 1.0)); valueAxis.setTickLabelOrientation(LabelOrientation.PERPENDICULAR); CategoryRenderer3D renderer = new LineRenderer3D(); CategoryPlot3D plot = new CategoryPlot3D(dataset, renderer, rowAxis, columnAxis, valueAxis); return new Chart3D(title, subtitle, plot); } /** * Creates and returns a scatter plot based on the supplied dataset * (containing one or more series of {@code (x, y, z)} values). The * chart returned by this method will be constructed with an * {@link XYZPlot} using a {@link ScatterXYZRenderer} (so it is safe * to cast the plot and/or renderer to customise attributes that are * specific to those subclasses). *

* For reference, here is a sample scatter chart: *
* ScatterPlot3DDemo1.svg *
* * @param title the chart title ({@code null} permitted). * @param subtitle the chart subtitle ({@code null} permitted). * @param dataset the dataset ({@code null} not permitted). * @param xAxisLabel the x-axis label ({@code null} permitted). * @param yAxisLabel the y-axis label ({@code null} permitted). * @param zAxisLabel the z-axis label ({@code null} permitted). * * @return The chart. */ public static Chart3D createScatterChart(String title, String subtitle, XYZDataset dataset, String xAxisLabel, String yAxisLabel, String zAxisLabel) { NumberAxis3D xAxis = new NumberAxis3D(xAxisLabel); NumberAxis3D yAxis = new NumberAxis3D(yAxisLabel); yAxis.setTickLabelOrientation(LabelOrientation.PERPENDICULAR); NumberAxis3D zAxis = new NumberAxis3D(zAxisLabel); XYZRenderer renderer = new ScatterXYZRenderer(); XYZPlot plot = new XYZPlot(dataset, renderer, xAxis, yAxis, zAxis); return new Chart3D(title, subtitle, plot); } /** * Creates a surface chart for the specified function. *

* For reference, here is a sample surface chart: *
* SurfaceRendererDemo2.svg *
* * @param title the chart title ({@code null} permitted). * @param subtitle the chart subtitle ({@code null} permitted). * @param function the function ({@code null} not permitted). * @param xAxisLabel the x-axis label ({@code null} permitted). * @param yAxisLabel the y-axis label ({@code null} permitted). * @param zAxisLabel the z-axis label ({@code null} permitted). * * @return The chart. * * @since 1.1 */ public static Chart3D createSurfaceChart(String title, String subtitle, Function3D function, String xAxisLabel, String yAxisLabel, String zAxisLabel) { NumberAxis3D xAxis = new NumberAxis3D(xAxisLabel); NumberAxis3D yAxis = new NumberAxis3D(yAxisLabel); yAxis.setTickLabelOrientation(LabelOrientation.PERPENDICULAR); NumberAxis3D zAxis = new NumberAxis3D(zAxisLabel); XYZRenderer renderer = new SurfaceRenderer(function); // we pass an empty dataset because the plot must have a non-null // dataset, but the renderer never looks at it... XYZPlot plot = new XYZPlot(new XYZSeriesCollection(), renderer, xAxis, yAxis, zAxis); Chart3D chart = new Chart3D(title, subtitle, plot); chart.setLegendBuilder(new ColorScaleLegendBuilder()); return chart; } /** * Creates and returns a bar chart based on the supplied dataset (this is * for special cases, most general cases will be covered by the * {@link #createBarChart(String, String, CategoryDataset3D, String, String, String) } * method). The chart returned by this method will be constructed with an * {@link XYZPlot} using a {@link BarXYZRenderer} (so it is safe * to cast the plot and/or renderer to customise attributes that are * specific to those subclasses). *

* For reference, here is a sample XYZ bar chart: *
* XYZBarChart3DDemo1.svg *
* * @param title the chart title ({@code null} permitted). * @param subtitle the chart subtitle ({@code null} permitted). * @param dataset the dataset ({@code null} not permitted). * @param xAxisLabel the x-axis label ({@code null} permitted). * @param yAxisLabel the y-axis label ({@code null} permitted). * @param zAxisLabel the z-axis label ({@code null} permitted). * * @return The chart. */ public static Chart3D createXYZBarChart(String title, String subtitle, XYZDataset dataset, String xAxisLabel, String yAxisLabel, String zAxisLabel) { ValueAxis3D xAxis = new NumberAxis3D(xAxisLabel); NumberAxis3D yAxis = new NumberAxis3D(yAxisLabel); yAxis.setTickLabelOrientation(LabelOrientation.PERPENDICULAR); ValueAxis3D zAxis = new NumberAxis3D(zAxisLabel); XYZRenderer renderer = new BarXYZRenderer(); XYZPlot plot = new XYZPlot(dataset, renderer, xAxis, yAxis, zAxis); return new Chart3D(title, subtitle, plot); } /** * Creates and returns a line chart based on the supplied dataset. The * chart returned by this method will be constructed with an * {@link XYZPlot} using a {@link LineXYZRenderer} (so it is safe * to cast the plot and/or renderer to customise attributes that are * specific to those subclasses). * * @param title the chart title ({@code null} permitted). * @param subtitle the chart subtitle ({@code null} permitted). * @param dataset the dataset ({@code null} not permitted). * @param xAxisLabel the x-axis label ({@code null} permitted). * @param yAxisLabel the y-axis label ({@code null} permitted). * @param zAxisLabel the z-axis label ({@code null} permitted). * * @return The chart. * * @since 1.5 */ public static Chart3D createXYZLineChart(String title, String subtitle, XYZDataset dataset, String xAxisLabel, String yAxisLabel, String zAxisLabel) { ValueAxis3D xAxis = new NumberAxis3D(xAxisLabel); NumberAxis3D yAxis = new NumberAxis3D(yAxisLabel); yAxis.setTickLabelOrientation(LabelOrientation.PERPENDICULAR); ValueAxis3D zAxis = new NumberAxis3D(zAxisLabel); XYZRenderer renderer = new LineXYZRenderer(); XYZPlot plot = new XYZPlot(dataset, renderer, xAxis, yAxis, zAxis); return new Chart3D(title, subtitle, plot); } } orson-charts-2.1.0/src/main/java/org/jfree/chart3d/Chart3DHints.java000066400000000000000000000067201417331271500251140ustar00rootroot00000000000000/* =========================================================== * Orson Charts : a 3D chart library for the Java(tm) platform * =========================================================== * * (C)opyright 2013-2022, by David Gilbert. All rights reserved. * * https://github.com/jfree/orson-charts * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . * * [Oracle and Java are registered trademarks of Oracle and/or its affiliates. * Other names may be trademarks of their respective owners.] * * If you do not wish to be bound by the terms of the GPL, an alternative * commercial license can be purchased. For details, please see visit the * Orson Charts home page: * * http://www.object-refinery.com/orsoncharts/index.html * */ package org.jfree.chart3d; import java.util.Map; /** * Special rendering hints that used internally by Orson Charts to provide * links between rendered items and the chart elements that they represent. * Most {@code Graphics2D} implementations will ignore these hints but * some, for example the {@code SVGGraphics2D} class in * JFreeSVG, will use the hints * to drive the output content. * * @since 1.3 */ public final class Chart3DHints { private Chart3DHints() { // no need to instantiate this } /** * The key for a hint to signal the beginning of an element. The value * should be a string containing the element id or, alternatively, a Map * containing the 'id' (String) and 'ref' (String in JSON format). */ public static final Key KEY_BEGIN_ELEMENT = new Chart3DHints.Key(0); /** * The key for a hint that ends an element. */ public static final Key KEY_END_ELEMENT = new Chart3DHints.Key(1); /** * A key for rendering hints that can be used with Orson Charts (in * addition to the regular Java2D rendering hints). */ public static class Key extends java.awt.RenderingHints.Key { /** * Creates a new key. * * @param privateKey the private key. */ public Key(int privateKey) { super(privateKey); } /** * Returns {@code true} if {@code val} is a value that is * compatible with this key, and {@code false} otherwise. * * @param val the value ({@code null} permitted). * * @return A boolean. */ @Override public boolean isCompatibleValue(Object val) { switch (intKey()) { case 0: return val == null || val instanceof String || val instanceof Map; case 1: return val == null || val instanceof Object; default: throw new RuntimeException("Not possible!"); } } } } orson-charts-2.1.0/src/main/java/org/jfree/chart3d/Chart3DPanel.java000066400000000000000000000213571417331271500250710ustar00rootroot00000000000000/* =========================================================== * Orson Charts : a 3D chart library for the Java(tm) platform * =========================================================== * * (C)opyright 2013-2022, by David Gilbert. All rights reserved. * * https://github.com/jfree/orson-charts * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . * * [Oracle and Java are registered trademarks of Oracle and/or its affiliates. * Other names may be trademarks of their respective owners.] * * If you do not wish to be bound by the terms of the GPL, an alternative * commercial license can be purchased. For details, please see visit the * Orson Charts home page: * * http://www.object-refinery.com/orsoncharts/index.html * */ package org.jfree.chart3d; import java.awt.event.ComponentEvent; import java.awt.event.ComponentListener; import java.awt.event.MouseEvent; import java.io.IOException; import java.io.ObjectInputStream; import java.util.EventListener; import javax.swing.event.EventListenerList; import org.jfree.chart3d.data.ItemKey; import org.jfree.chart3d.graphics3d.Object3D; import org.jfree.chart3d.graphics3d.RenderedElement; import org.jfree.chart3d.graphics3d.RenderingInfo; import org.jfree.chart3d.graphics3d.swing.DisplayPanel3D; import org.jfree.chart3d.graphics3d.swing.Panel3D; import org.jfree.chart3d.interaction.Chart3DMouseEvent; import org.jfree.chart3d.interaction.Chart3DMouseListener; import org.jfree.chart3d.internal.Args; /** * A panel designed to display a {@link Chart3D} in a Swing-based desktop * application. The panel registers with the chart to receive change * notifications, and when these are received the chart is automatically * repainted. *

* This panel will display the chart, but does not include additional features * such as the view toolbar and popup menu (these are provided by the * {@link DisplayPanel3D} class). *

* NOTE: This class is serializable, but the serialization format is subject * to change in future releases and should not be relied upon for persisting * instances of this class. */ @SuppressWarnings("serial") public class Chart3DPanel extends Panel3D implements Chart3DChangeListener, ComponentListener { /** * The chart being rendered. */ private final Chart3D chart; /** Auto-fit the chart on resize? */ private final boolean autoFitOnPanelResize; /** Storage for registered (chart) mouse listeners. */ private transient EventListenerList chartMouseListeners; /** * Creates a new chart panel to display the specified chart. * * @param chart the chart. */ public Chart3DPanel(Chart3D chart) { super(chart); this.chartMouseListeners = new EventListenerList(); this.chart = chart; this.chart.addChangeListener(this); addComponentListener(this); this.autoFitOnPanelResize = false; registerForTooltips(); } /** * Returns the chart being displayed in this panel. * * @return The chart (never {@code null}). * * @since 1.3 */ public Chart3D getChart() { return this.chart; } /** * Receives notification when the chart has been modified, and responds * by completely repainting the panel and chart. * * @param event the event. */ @Override public void chartChanged(Chart3DChangeEvent event) { repaint(); } @Override public void componentResized(ComponentEvent e) { if (this.autoFitOnPanelResize) { zoomToFit(); } } @Override public void componentMoved(ComponentEvent e) { // do nothing } @Override public void componentShown(ComponentEvent e) { // do nothing } @Override public void componentHidden(ComponentEvent e) { // do nothing } @Override public String getToolTipText(MouseEvent e) { RenderingInfo info = getRenderingInfo(); if (info == null) { return null; } Object3D object = info.fetchObjectAt(e.getX(), e.getY()); if (object != null) { ItemKey key = (ItemKey) object.getProperty(Object3D.ITEM_KEY); if (key != null) { return chart.getPlot().generateToolTipText(key); } } return null; } /** * Receives a mouse event and passes it on to registered * {@link Chart3DMouseListener}s along with the underlying rendered * element if any. * * @param e the mouse event. */ @Override public void mouseClicked(MouseEvent e) { Object[] listeners = this.chartMouseListeners.getListeners( Chart3DMouseListener.class); if (listeners.length == 0) { return; } RenderedElement element = null; RenderingInfo info = getRenderingInfo(); if (info != null) { element = info.findElementAt(e.getX(), e.getY()); } Chart3DMouseEvent chartEvent = new Chart3DMouseEvent(this.chart, e, element); for (int i = listeners.length - 1; i >= 0; i -= 1) { ((Chart3DMouseListener) listeners[i]).chartMouseClicked(chartEvent); } super.mouseClicked(e); } /** * Receives a mouse event and passes it on to registered * {@link Chart3DMouseListener}s along with the underlying rendered * element if any. * * @param e the mouse event. */ @Override public void mouseMoved(MouseEvent e) { Object[] listeners = this.chartMouseListeners.getListeners( Chart3DMouseListener.class); if (listeners.length == 0) { return; } RenderedElement element = null; RenderingInfo info = getRenderingInfo(); if (info != null) { element = info.findElementAt(e.getX(), e.getY()); } Chart3DMouseEvent chartEvent = new Chart3DMouseEvent(this.chart, e, element); for (int i = listeners.length - 1; i >= 0; i -= 1) { ((Chart3DMouseListener) listeners[i]).chartMouseMoved(chartEvent); } super.mouseMoved(e); } /** * Adds a listener to the list of objects listening for chart mouse events. * * @param listener the listener ({@code null} not permitted). * * @since 1.3 */ public void addChartMouseListener(Chart3DMouseListener listener) { Args.nullNotPermitted(listener, "listener"); this.chartMouseListeners.add(Chart3DMouseListener.class, listener); } /** * Removes a listener from the list of objects listening for chart mouse * events. * * @param listener the listener ({@code null} not permitted). * * @since 1.3 */ public void removeChartMouseListener(Chart3DMouseListener listener) { Args.nullNotPermitted(listener, "listener"); this.chartMouseListeners.remove(Chart3DMouseListener.class, listener); } /** * Returns an array of the listeners of the given type registered with the * panel. * * @param listenerType the listener type. * * @return An array of listeners. */ @Override public T[] getListeners(Class listenerType) { if (listenerType == Chart3DMouseListener.class) { // fetch listeners from local storage return this.chartMouseListeners.getListeners(listenerType); } else { return super.getListeners(listenerType); } } /** * Provides serialization support. * * @param stream the input stream. * * @throws IOException if there is an I/O error. * @throws ClassNotFoundException if there is a classpath problem. */ private void readObject(ObjectInputStream stream) throws IOException, ClassNotFoundException { stream.defaultReadObject(); // we create a new but empty chartMouseListeners list this.chartMouseListeners = new EventListenerList(); // register as a listener with sub-components... if (this.chart != null) { this.chart.addChangeListener(this); } } } orson-charts-2.1.0/src/main/java/org/jfree/chart3d/ChartElement.java000066400000000000000000000033421417331271500252260ustar00rootroot00000000000000/* =========================================================== * Orson Charts : a 3D chart library for the Java(tm) platform * =========================================================== * * (C)opyright 2013-2022, by David Gilbert. All rights reserved. * * https://github.com/jfree/orson-charts * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . * * [Oracle and Java are registered trademarks of Oracle and/or its affiliates. * Other names may be trademarks of their respective owners.] * * If you do not wish to be bound by the terms of the GPL, an alternative * commercial license can be purchased. For details, please see visit the * Orson Charts home page: * * http://www.object-refinery.com/orsoncharts/index.html * */ package org.jfree.chart3d; /** * A chart element used to implement the Visitor pattern for applying changes * to the chart. This is used by the chart styling feature. * * @since 1.2 */ public interface ChartElement { /** * Receives a visitor to the element. * * @param visitor the visitor ({@code null} not permitted). */ void receive(ChartElementVisitor visitor); } orson-charts-2.1.0/src/main/java/org/jfree/chart3d/ChartElementVisitor.java000066400000000000000000000031521417331271500266050ustar00rootroot00000000000000/* =========================================================== * Orson Charts : a 3D chart library for the Java(tm) platform * =========================================================== * * (C)opyright 2013-2022, by David Gilbert. All rights reserved. * * https://github.com/jfree/orson-charts * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . * * [Oracle and Java are registered trademarks of Oracle and/or its affiliates. * Other names may be trademarks of their respective owners.] * * If you do not wish to be bound by the terms of the GPL, an alternative * commercial license can be purchased. For details, please see visit the * Orson Charts home page: * * http://www.object-refinery.com/orsoncharts/index.html * */ package org.jfree.chart3d; /** * A visitor for a {@link ChartElement}. */ public interface ChartElementVisitor { /** * Visit a chart element. * * @param element the chart element ({@code null} not permitted). */ void visit(ChartElement element); } orson-charts-2.1.0/src/main/java/org/jfree/chart3d/Colors.java000066400000000000000000000550331417331271500241200ustar00rootroot00000000000000/* =========================================================== * Orson Charts : a 3D chart library for the Java(tm) platform * =========================================================== * * (C)opyright 2013-2022, by David Gilbert. All rights reserved. * * https://github.com/jfree/orson-charts * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . * * [Oracle and Java are registered trademarks of Oracle and/or its affiliates. * Other names may be trademarks of their respective owners.] * * If you do not wish to be bound by the terms of the GPL, an alternative * commercial license can be purchased. For details, please see visit the * Orson Charts home page: * * http://www.object-refinery.com/orsoncharts/index.html * */ package org.jfree.chart3d; import java.awt.Color; /** * A utility class that creates and returns color swatches that can be used * in charts. The "i want hue" utility has been used to generate a number * of these color sets. * See * http://tools.medialab.sciences-po.fr/iwanthue/. */ public class Colors { private Colors() { // no need to instantiate this class } /** * Returns the default colors. * * @return The default colors. */ public static Color[] getDefaultColors() { return createShadesColors(); } /** * Returns a palette of ten colors created using the "i want hue" utility, * using the preset "Fancy (light background)" settings. A new array * instance is created for each call to this method. A link to the * "i want hue" utility is given in the class description. * * @return An array of ten colors (never {@code null}). * * @since 1.2 */ public static Color[] createFancyLightColors() { Color[] result = new Color[10]; result[0] = new Color(239, 164, 127); result[1] = new Color(140, 228, 139); result[2] = new Color(155, 208, 227); result[3] = new Color(221, 228, 95); result[4] = new Color(118, 223, 194); result[5] = new Color(240, 166, 184); result[6] = new Color(231, 185, 98); result[7] = new Color(186, 214, 150); result[8] = new Color(217, 184, 226); result[9] = new Color(201, 212, 116); return result; } /** * Returns a palette of ten colors created using the "i want hue" utility, * using the preset "Fancy (dark background)" settings. A new array * instance is created for each call to this method. A link to the * "i want hue" utility is given in the class description. * * @return An array of ten colors (never {@code null}). * * @since 1.2 */ public static Color[] createFancyDarkColors() { Color[] result = new Color[10]; result[0] = new Color(78, 81, 97); result[1] = new Color(91, 104, 51); result[2] = new Color(138, 75, 65); result[3] = new Color(72, 62, 34); result[4] = new Color(58, 100, 75); result[5] = new Color(39, 63, 59); result[6] = new Color(105, 68, 75); result[7] = new Color(120, 90, 120); result[8] = new Color(119, 90, 50); result[9] = new Color(59, 103, 111); return result; } /** * Returns a palette of ten colors created using the "i want hue" utility, * using the preset "Shades" settings. A new array instance is created for * each call to this method. A link to the "i want hue" utility is given * in the class description. * * @return An array of ten colors (never {@code null}). * * @since 1.2 */ public static Color[] createShadesColors() { Color[] result = new Color[10]; result[0] = new Color(137, 132, 104); result[1] = new Color(217, 232, 208); result[2] = new Color(53, 48, 40); result[3] = new Color(240, 225, 172); result[4] = new Color(196, 160, 128); result[5] = new Color(92, 96, 87); result[6] = new Color(136, 141, 136); result[7] = new Color(106, 93, 66); result[8] = new Color(205, 199, 168); result[9] = new Color(158, 168, 143); return result; } /** * Returns a palette of ten colors created using the "i want hue" utility, * using the preset "Tarnish" settings. A new array instance is created for * each call to this method. A link to the "i want hue" utility is given * in the class description. * * @return An array of ten colors (never {@code null}). * * @since 1.2 */ public static Color[] createTarnishColors() { Color[] result = new Color[10]; result[0] = new Color(148, 129, 121); result[1] = new Color(179, 181, 136); result[2] = new Color(204, 163, 140); result[3] = new Color(102, 93, 80); result[4] = new Color(164, 178, 159); result[5] = new Color(156, 130, 100); result[6] = new Color(129, 142, 124); result[7] = new Color(186, 168, 159); result[8] = new Color(144, 148, 108); result[9] = new Color(189, 169, 131); return result; } /** * Returns a palette of ten colors created using the "i want hue" utility, * using the preset "Pastel" settings. A new array instance is created for * each call to this method. A link to the "i want hue" utility is given * in the class description. * * @return An array of ten colors (never {@code null}). * * @since 1.2 */ public static Color[] createPastelColors() { Color[] result = new Color[10]; result[0] = new Color(232, 177, 165); result[1] = new Color(207, 235, 142); result[2] = new Color(142, 220, 220); result[3] = new Color(228, 186, 115); result[4] = new Color(187, 200, 230); result[5] = new Color(157, 222, 177); result[6] = new Color(234, 183, 210); result[7] = new Color(213, 206, 169); result[8] = new Color(202, 214, 205); result[9] = new Color(195, 204, 133); return result; } /** * Returns a palette of ten colors created using the "i want hue" utility, * using the preset "Pimp" settings. A new array instance is created for * each call to this method. A link to the "i want hue" utility is given * in the class description. * * @return An array of ten colors (never {@code null}). * * @since 1.2 */ public static Color[] createPimpColors() { Color[] result = new Color[10]; result[0] = new Color(197, 75, 103); result[1] = new Color(85, 154, 48); result[2] = new Color(122, 110, 206); result[3] = new Color(190, 100, 50); result[4] = new Color(201, 79, 209); result[5] = new Color(95, 127, 170); result[6] = new Color(147, 129, 39); result[7] = new Color(63, 142, 96); result[8] = new Color(186, 84, 150); result[9] = new Color(219, 66, 52); return result; } /** * Returns a palette of ten colors created using the "i want hue" utility, * using the preset "Intense" settings. A new array instance is created for * each call to this method. A link to the "i want hue" utility is given * in the class description. * * @return An array of ten colors (never {@code null}). * * @since 1.2 */ public static Color[] createIntenseColors() { Color[] result = new Color[10]; result[0] = new Color(107, 122, 160); result[1] = new Color(99, 176, 67); result[2] = new Color(214, 85, 52); result[3] = new Color(202, 79, 200); result[4] = new Color(184, 149, 57); result[5] = new Color(82, 168, 146); result[6] = new Color(194, 84, 128); result[7] = new Color(77, 102, 50); result[8] = new Color(132, 108, 197); result[9] = new Color(144, 74, 61); return result; } /** * Returns a palette of ten colors created using the "i want hue" utility, * using the preset "Fluo" settings. A new array instance is created for * each call to this method. A link to the "i want hue" utility is given * in the class description. * * @return An array of ten colors (never {@code null}). * * @since 1.2 */ public static Color[] createFluoColors() { Color[] result = new Color[10]; result[0] = new Color(108, 236, 137); result[1] = new Color(253, 187, 46); result[2] = new Color(56, 236, 216); result[3] = new Color(171, 231, 51); result[4] = new Color(221, 214, 74); result[5] = new Color(106, 238, 70); result[6] = new Color(172, 230, 100); result[7] = new Color(242, 191, 82); result[8] = new Color(221, 233, 56); result[9] = new Color(242, 206, 47); return result; } /** * Returns a palette of ten colors created using the "i want hue" utility, * using the preset "Red Roses" settings. A new array instance is created * for each call to this method. A link to the "i want hue" utility is * given in the class description. * * @return An array of ten colors (never {@code null}). * * @since 1.2 */ public static Color[] createRedRosesColors() { Color[] result = new Color[10]; result[0] = new Color(230, 129, 128); result[1] = new Color(233, 56, 39); result[2] = new Color(225, 45, 102); result[3] = new Color(172, 79, 55); result[4] = new Color(214, 154, 128); result[5] = new Color(156, 96, 81); result[6] = new Color(190, 77, 91); result[7] = new Color(228, 121, 91); result[8] = new Color(216, 63, 80); result[9] = new Color(209, 75, 46); return result; } /** * Returns a palette of ten colors created using the "i want hue" utility, * using the preset "Ochre Sand" settings. A new array instance is created * for each call to this method. A link to the "i want hue" utility is * given in the class description. * * @return An array of ten colors (never {@code null}). * * @since 1.2 */ public static Color[] createOchreSandColors() { Color[] result = new Color[10]; result[0] = new Color(218, 180, 125); result[1] = new Color(245, 184, 36); result[2] = new Color(159, 103, 28); result[3] = new Color(124, 96, 55); result[4] = new Color(224, 132, 56); result[5] = new Color(185, 143, 48); result[6] = new Color(229, 171, 97); result[7] = new Color(232, 165, 54); result[8] = new Color(171, 102, 53); result[9] = new Color(160, 122, 71); return result; } /** * Returns a palette of ten colors created using the "i want hue" utility, * using the preset "Yellow Lime" settings. A new array instance is created * for each call to this method. A link to the "i want hue" utility is * given in the class description. * * @return An array of ten colors (never {@code null}). * * @since 1.2 */ public static Color[] createYellowLimeColors() { Color[] result = new Color[10]; result[0] = new Color(235, 203, 59); result[1] = new Color(113, 108, 56); result[2] = new Color(222, 206, 134); result[3] = new Color(169, 166, 62); result[4] = new Color(214, 230, 54); result[5] = new Color(225, 221, 105); result[6] = new Color(128, 104, 23); result[7] = new Color(162, 151, 86); result[8] = new Color(117, 121, 25); result[9] = new Color(183, 179, 40); return result; } /** * Returns a palette of ten colors created using the "i want hue" utility, * using the preset "Green Mint" settings. A new array instance is created * for each call to this method. A link to the "i want hue" utility is * given in the class description. * * @return An array of ten colors (never {@code null}). * * @since 1.2 */ public static Color[] createGreenMintColors() { Color[] result = new Color[10]; result[0] = new Color(99, 224, 113); result[1] = new Color(98, 132, 83); result[2] = new Color(145, 234, 49); result[3] = new Color(181, 215, 158); result[4] = new Color(95, 171, 43); result[5] = new Color(100, 208, 142); result[6] = new Color(172, 222, 84); result[7] = new Color(75, 139, 53); result[8] = new Color(177, 216, 123); result[9] = new Color(83, 223, 60); return result; } /** * Returns a palette of ten colors created using the "i want hue" utility, * using the preset "Ice Cube" settings. A new array instance is created * for each call to this method. A link to the "i want hue" utility is * given in the class description. * * @return An array of ten colors (never {@code null}). * * @since 1.2 */ public static Color[] createIceCubeColors() { Color[] result = new Color[10]; result[0] = new Color(112, 235, 233); result[1] = new Color(54, 110, 100); result[2] = new Color(211, 232, 208); result[3] = new Color(94, 230, 191); result[4] = new Color(76, 154, 155); result[5] = new Color(156, 181, 157); result[6] = new Color(67, 152, 126); result[7] = new Color(112, 135, 119); result[8] = new Color(155, 213, 192); result[9] = new Color(80, 195, 190); return result; } /** * Returns a palette of ten colors created using the "i want hue" utility, * using the preset "Blue Ocean" settings. A new array instance is created * for each call to this method. A link to the "i want hue" utility is * given in the class description. * * @return An array of ten colors (never {@code null}). * * @since 1.2 */ public static Color[] createBlueOceanColors() { Color[] result = new Color[10]; result[0] = new Color(53, 84, 154); result[1] = new Color(41, 46, 57); result[2] = new Color(115, 124, 151); result[3] = new Color(38, 52, 91); result[4] = new Color(84, 117, 211); result[5] = new Color(76, 125, 181); result[6] = new Color(109, 108, 112); result[7] = new Color(48, 105, 134); result[8] = new Color(72, 82, 107); result[9] = new Color(91, 99, 144); return result; } /** * Returns a palette of ten colors created using the "i want hue" utility, * using the preset "Indigo Night" settings. A new array instance is * created for each call to this method. A link to the "i want hue" * utility is given in the class description. * * @return An array of ten colors (never {@code null}). * * @since 1.2 */ public static Color[] createIndigoNightColors() { Color[] result = new Color[10]; result[0] = new Color(127, 88, 147); result[1] = new Color(201, 67, 217); result[2] = new Color(112, 97, 218); result[3] = new Color(219, 134, 222); result[4] = new Color(154, 80, 172); result[5] = new Color(170, 106, 231); result[6] = new Color(142, 111, 210); result[7] = new Color(194, 149, 235); result[8] = new Color(152, 118, 188); result[9] = new Color(214, 101, 237); return result; } /** * Returns a palette of ten colors created using the "i want hue" utility, * using the preset "Purple Wine" settings. A new array instance is created * for each call to this method. A link to the "i want hue" utility is * given in the class description. * * @return An array of ten colors (never {@code null}). * * @since 1.2 */ public static Color[] createPurpleWineColors() { Color[] result = new Color[10]; result[0] = new Color(116, 28, 93); result[1] = new Color(112, 79, 75); result[2] = new Color(178, 37, 101); result[3] = new Color(109, 24, 56); result[4] = new Color(167, 42, 140); result[5] = new Color(66, 30, 40); result[6] = new Color(128, 70, 95); result[7] = new Color(78, 20, 56); result[8] = new Color(155, 62, 111); result[9] = new Color(139, 61, 75); return result; } /** * Returns a palette of 7 colors with earth tones. * * @return An array of 7 colors (never {@code null}). */ public static Color[] getEarthColors() { Color[] result = new Color[7]; result[0] = new Color(98, 98, 98); result[1] = new Color(159, 87, 43); result[2] = new Color(194, 176, 46); result[3] = new Color(134, 155, 64); result[4] = new Color(57, 118, 40); result[5] = new Color(40, 114, 110); result[6] = new Color(78, 79, 62); return result; } /** * Returns a newly created array containing 9 colors from the the * ColorBrewer tool. This is a high-contrast set of colors, good for * pie charts. * * http://colorbrewer2.org/?type=qualitative&scheme=Set1&n=9 * * @return A color array. */ public static Color[] getBrewerQualitativeSet1N9Colors() { Color[] result = new Color[9]; result[0] = new Color(228, 26, 28); result[1] = new Color(55, 126, 184); result[2] = new Color(77, 175, 74); result[3] = new Color(152, 78, 163); result[4] = new Color(255, 127, 0); result[5] = new Color(255, 255, 51); result[6] = new Color(166, 86, 40); result[7] = new Color(247, 129, 191); result[8] = new Color(153, 153, 153); return result; } /** * Returns a newly created array containing 12 colors from the the * ColorBrewer tool. * * http://colorbrewer2.org/?type=qualitative&scheme=Paired&n=12 * * @return A color array. */ public static Color[] getBrewerQualitativePairedN12Colors() { Color[] result = new Color[12]; result[0] = new Color(166, 206, 227); result[1] = new Color(31, 120, 180); result[2] = new Color(178, 223, 138); result[3] = new Color(51, 160, 44); result[4] = new Color(251, 154, 153); result[5] = new Color(227, 26, 28); result[6] = new Color(253, 191, 111); result[7] = new Color(255, 127, 0); result[8] = new Color(202, 178, 214); result[9] = new Color(106, 61, 154); result[10] = new Color(255, 255, 153); result[11] = new Color(177, 89, 40); return result; } /** * Returns a newly created array containing 11 colors from the the * ColorBrewer tool. Good for pie charts and bar charts, not so good for * scatter plots. * * http://colorbrewer2.org/?type=qualitative&scheme=Set3&n=12 * * @return A color array. */ public static Color[] getBrewerQualitativeSet3N12Colors() { Color[] result = new Color[12]; result[0] = new Color(141, 211, 199); result[1] = new Color(255, 255, 179); result[2] = new Color(190, 186, 218); result[3] = new Color(251, 128, 114); result[4] = new Color(128, 177, 211); result[5] = new Color(253, 180, 98); result[6] = new Color(179, 222, 105); result[7] = new Color(252, 205, 229); result[8] = new Color(217, 217, 217); result[9] = new Color(188, 128, 189); result[10] = new Color(204, 235, 197); result[11] = new Color(255, 237, 111); return result; } /** * Returns a set of colors sourced from * http://www.sapdesignguild.org/goodies/diagram_guidelines/index.html. * * @return A color array. */ public static Color[] getSAPMultiColor() { return new Color[] { new Color(255, 248, 163), new Color(169, 204, 143), new Color(178, 200, 217), new Color(190, 163, 122), new Color(243, 170, 121), new Color(181, 181, 169), new Color(230, 165, 164), new Color(248, 215, 83), new Color(92, 151, 70), new Color(62, 117, 167), new Color(122, 101, 62), new Color(225, 102, 42), new Color(116, 121, 111), new Color(196, 56, 79) }; } /** * Returns an array of four colors. * * @return An array of four colors. */ public static Color[] getColors1() { return new Color[] { new Color(0, 55, 122), new Color(24, 123, 58), Color.RED, Color.YELLOW }; } /** * Returns an array of four colors. * * @return An array of four colors. */ public static Color[] getColors2() { return new Color[] {new Color(0x1A9641), new Color(0xA6D96A), new Color(0xFDAE61), new Color(0xFFFFBF)}; } /** * Returns an array of six colors * (source: http://blog.design-seeds.com/generating-color/). * * @return An array of six colors. */ public static Color[] getDesignSeedsShells() { return new Color[] { new Color(228, 233, 239), new Color(184, 197, 219), new Color(111, 122, 143), new Color(95, 89, 89), new Color(206, 167, 145), new Color(188, 182, 173) }; } /** * Returns an array of six colors * (source: http://blog.design-seeds.com/generating-color/). * * @return An array of six colors. */ public static Color[] getDesignSeedsPepper() { return new Color[] { new Color(255, 219, 142), new Color(220, 21, 20), new Color(149, 0, 1), new Color(82, 102, 41), new Color(142, 101, 72), new Color(199, 169, 128) }; } } orson-charts-2.1.0/src/main/java/org/jfree/chart3d/Orientation.java000066400000000000000000000032441417331271500251470ustar00rootroot00000000000000/* =========================================================== * Orson Charts : a 3D chart library for the Java(tm) platform * =========================================================== * * (C)opyright 2013-2022, by David Gilbert. All rights reserved. * * https://github.com/jfree/orson-charts * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . * * [Oracle and Java are registered trademarks of Oracle and/or its affiliates. * Other names may be trademarks of their respective owners.] * * If you do not wish to be bound by the terms of the GPL, an alternative * commercial license can be purchased. For details, please see visit the * Orson Charts home page: * * http://www.object-refinery.com/orsoncharts/index.html * */ package org.jfree.chart3d; /** * General enumeration of orientations. One application for this is to * specify whether the legend should be created for a vertical or horizontal * layout. * * @since 1.1 */ public enum Orientation { /** Horizontal orientation. */ HORIZONTAL, /** Vertical orientation. */ VERTICAL } orson-charts-2.1.0/src/main/java/org/jfree/chart3d/Resources.java000066400000000000000000000053041417331271500246250ustar00rootroot00000000000000/* =========================================================== * Orson Charts : a 3D chart library for the Java(tm) platform * =========================================================== * * (C)opyright 2013-2022, by David Gilbert. All rights reserved. * * https://github.com/jfree/orson-charts * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . * * [Oracle and Java are registered trademarks of Oracle and/or its affiliates. * Other names may be trademarks of their respective owners.] * * If you do not wish to be bound by the terms of the GPL, an alternative * commercial license can be purchased. For details, please see visit the * Orson Charts home page: * * http://www.object-refinery.com/orsoncharts/index.html * */ package org.jfree.chart3d; import java.util.Locale; import java.util.ResourceBundle; import org.jfree.chart3d.internal.Args; /** * Provides centralised access to localised resources. * * @since 1.2 */ public class Resources { /** The locale for the resources. */ private static Locale locale = Locale.getDefault(); /** Localised resources. */ private static ResourceBundle resources = ResourceBundle.getBundle( "org.jfree.chart3d.Resources", Locale.getDefault()); /** * Returns the locale that is being used for supplying resources. The * default value is {@code Locale.getDefault()}. * * @return The locale (never {@code null}). */ public static Locale getLocale() { return locale; } /** * Sets the locale to use for supplying resources. * * @param l the locale ({@code null} not permitted). */ public static void setLocale(Locale l) { Args.nullNotPermitted(l, "l"); locale = l; resources = ResourceBundle.getBundle("org.jfree.chart3d.Resources", locale); } /** * Returns a localised string. * * @param key the key ({@code null} not permitted). * * @return A localised string. */ public static String localString(String key) { return resources.getString(key); } } orson-charts-2.1.0/src/main/java/org/jfree/chart3d/TitleAnchor.java000066400000000000000000000065161417331271500250750ustar00rootroot00000000000000/* =========================================================== * Orson Charts : a 3D chart library for the Java(tm) platform * =========================================================== * * (C)opyright 2013-2022, by David Gilbert. All rights reserved. * * https://github.com/jfree/orson-charts * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . * * [Oracle and Java are registered trademarks of Oracle and/or its affiliates. * Other names may be trademarks of their respective owners.] * * If you do not wish to be bound by the terms of the GPL, an alternative * commercial license can be purchased. For details, please see visit the * Orson Charts home page: * * http://www.object-refinery.com/orsoncharts/index.html * */ package org.jfree.chart3d; import org.jfree.chart3d.graphics2d.Anchor2D; import org.jfree.chart3d.graphics2d.RefPt2D; /** * Predefined title anchor points, provided for convenience. These anchor * points are instances of the {@link Anchor2D} class, initialised with an * offset of 4 units from each corner of the target rectangle. */ public final class TitleAnchor { /** * An anchor point at the top-left of the chart area. */ public static final Anchor2D TOP_LEFT = new Anchor2D(RefPt2D.TOP_LEFT); /** * An anchor point at the top-right of the chart area. */ public static final Anchor2D TOP_RIGHT = new Anchor2D(RefPt2D.TOP_RIGHT); /** * An anchor point at the top-center of the chart area. */ public static final Anchor2D TOP_CENTER = new Anchor2D(RefPt2D.TOP_CENTER); /** * An anchor point at the center-left of the chart area. */ public static final Anchor2D CENTER_LEFT = new Anchor2D(RefPt2D.CENTER_LEFT); /** * An anchor point at the center of the chart area (provided for * completeness, you wouldn't normally anchor a chart title at the * center). */ public static final Anchor2D CENTER = new Anchor2D(RefPt2D.CENTER); /** * An anchor point at the center-right of the chart area. */ public static final Anchor2D CENTER_RIGHT = new Anchor2D(RefPt2D.CENTER_RIGHT); /** * An anchor point at the bottom-center of the chart area. */ public static final Anchor2D BOTTOM_CENTER = new Anchor2D(RefPt2D.BOTTOM_CENTER); /** * An anchor point at the bottom-left of the chart area. */ public static final Anchor2D BOTTOM_LEFT = new Anchor2D(RefPt2D.BOTTOM_LEFT); /** * An anchor point at the bottom-right of the chart area. */ public static final Anchor2D BOTTOM_RIGHT = new Anchor2D(RefPt2D.BOTTOM_RIGHT); private TitleAnchor() { // no need to instantiate this } } orson-charts-2.1.0/src/main/java/org/jfree/chart3d/TitleUtils.java000066400000000000000000000132631417331271500247600ustar00rootroot00000000000000/* =========================================================== * Orson Charts : a 3D chart library for the Java(tm) platform * =========================================================== * * (C)opyright 2013-2022, by David Gilbert. All rights reserved. * * https://github.com/jfree/orson-charts * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . * * [Oracle and Java are registered trademarks of Oracle and/or its affiliates. * Other names may be trademarks of their respective owners.] * * If you do not wish to be bound by the terms of the GPL, an alternative * commercial license can be purchased. For details, please see visit the * Orson Charts home page: * * http://www.object-refinery.com/orsoncharts/index.html * */ package org.jfree.chart3d; import java.awt.Color; import java.awt.Font; import org.jfree.chart3d.graphics2d.Anchor2D; import org.jfree.chart3d.interaction.InteractiveElementType; import org.jfree.chart3d.table.GridElement; import org.jfree.chart3d.table.HAlign; import org.jfree.chart3d.table.TableElement; import org.jfree.chart3d.table.TextElement; /** * Some utility methods for creating chart titles. */ public class TitleUtils { /** The default title font. */ public static final Font DEFAULT_TITLE_FONT = new Font("Dialog", Font.BOLD, 20); /** The default foreground color for titles. */ public static final Color DEFAULT_TITLE_COLOR = Color.BLACK; /** The default sub-title font. */ public static final Font DEFAULT_SUBTITLE_FONT = new Font("Dialog", Font.PLAIN, 12); private TitleUtils() { // no need to instantiate this class } /** * Creates a chart title using the default font and alignment. * * @param title the chart title ({@code null} not permitted). * * @return The chart title. */ public static TableElement createTitle(String title) { return createTitle(title, null); } /** * Creates a chart title and subtitle using default fonts and left * alignment. The {@code subtitle} is optional. * * @param title the title text ({@code null} not permitted). * @param subtitle the subtitle text ({@code null} permitted). * * @return A composite title. */ public static TableElement createTitle(String title, String subtitle) { return createTitle(title, subtitle, TitleAnchor.TOP_LEFT); } /** * Creates a chart title and subtitle (optional) using default fonts and * alignment that is standard for the specified anchor point (that is, left * alignment when the title is anchored left, center alignment when the * title is anchored centrally, and right alignment when the title is * anchored to the right). * * @param title the title text ({@code null} not permitted). * @param subtitle the subtitle text ({@code null} permitted). * @param anchor the anchor point ({@code null} not permitted). * * @return A composite title. */ public static TableElement createTitle(String title, String subtitle, Anchor2D anchor) { HAlign alignment = HAlign.LEFT; if (anchor.getRefPt().isHorizontalCenter()) { alignment = HAlign.CENTER; } else if (anchor.getRefPt().isRight()) { alignment = HAlign.RIGHT; } return createTitle(title, DEFAULT_TITLE_FONT, subtitle, DEFAULT_SUBTITLE_FONT, alignment); } /** * Creates a chart title and subtitle using the specified fonts and * alignment. * * @param title the title text ({@code null} not permitted). * @param titleFont the title font ({@code null} not permitted). * @param subtitle the subtitle text ({@code null} permitted). * @param subtitleFont the subtitle font ({@code null} permitted). * @param alignment the horizontal alignment ({@code null} not * permitted). * * @return A chart title (never {@code null}). */ public static TableElement createTitle(String title, Font titleFont, String subtitle, Font subtitleFont, HAlign alignment) { TextElement t = new TextElement(title, titleFont); t.setHorizontalAligment(alignment); t.setColor(DEFAULT_TITLE_COLOR); t.setTag("CHART_TITLE"); t.setProperty(TableElement.CLASS, InteractiveElementType.TITLE); if (subtitle == null) { return t; } if (subtitleFont == null) { throw new IllegalArgumentException( "A subtitleFont is required when there is a subtitle."); } GridElement compositeTitle = new GridElement<>(); TextElement st = new TextElement(subtitle, subtitleFont); st.setHorizontalAligment(alignment); st.setColor(DEFAULT_TITLE_COLOR); st.setTag("CHART_SUBTITLE"); st.setProperty(TableElement.CLASS, InteractiveElementType.SUBTITLE); compositeTitle.setElement(t, "R1", "C1"); compositeTitle.setElement(st, "R2", "C1"); return compositeTitle; } } orson-charts-2.1.0/src/main/java/org/jfree/chart3d/axis/000077500000000000000000000000001417331271500227525ustar00rootroot00000000000000orson-charts-2.1.0/src/main/java/org/jfree/chart3d/axis/AbstractAxis3D.java000066400000000000000000000537721417331271500264120ustar00rootroot00000000000000/* =========================================================== * Orson Charts : a 3D chart library for the Java(tm) platform * =========================================================== * * (C)opyright 2013-2022, by David Gilbert. All rights reserved. * * https://github.com/jfree/orson-charts * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . * * [Oracle and Java are registered trademarks of Oracle and/or its affiliates. * Other names may be trademarks of their respective owners.] * * If you do not wish to be bound by the terms of the GPL, an alternative * commercial license can be purchased. For details, please see visit the * Orson Charts home page: * * http://www.object-refinery.com/orsoncharts/index.html * */ package org.jfree.chart3d.axis; import java.awt.BasicStroke; import java.awt.Color; import java.awt.Font; import java.awt.Graphics2D; import java.awt.Shape; import java.awt.Stroke; import java.awt.geom.Line2D; import java.awt.geom.Point2D; import java.io.IOException; import java.io.ObjectInputStream; import java.io.ObjectOutputStream; import java.io.Serializable; import java.util.HashMap; import java.util.List; import java.util.Map; import javax.swing.event.EventListenerList; import org.jfree.chart3d.internal.Args; import org.jfree.chart3d.internal.ObjectUtils; import org.jfree.chart3d.internal.SerialUtils; import org.jfree.chart3d.internal.TextUtils; import org.jfree.chart3d.Chart3DHints; import org.jfree.chart3d.ChartElementVisitor; import org.jfree.chart3d.graphics2d.TextAnchor; import org.jfree.chart3d.graphics3d.RenderedElement; import org.jfree.chart3d.graphics3d.RenderingInfo; import org.jfree.chart3d.graphics3d.internal.Utils2D; import org.jfree.chart3d.interaction.InteractiveElementType; import org.jfree.chart3d.marker.MarkerChangeEvent; import org.jfree.chart3d.marker.MarkerChangeListener; import org.jfree.chart3d.plot.CategoryPlot3D; /** * A base class that can be used to create an {@link Axis3D} implementation. * This class implements the core axis attributes as well as the change * listener mechanism required to enable automatic repainting of charts. *

* NOTE: This class is serializable, but the serialization format is subject * to change in future releases and should not be relied upon for persisting * instances of this class. */ public abstract class AbstractAxis3D implements Axis3D, MarkerChangeListener, Serializable { /** * The default axis label font (in most circumstances this will be * overridden by the chart style). * * @since 1.2 */ public static final Font DEFAULT_LABEL_FONT = new Font("Dialog", Font.BOLD, 12); /** * The default axis label color (in most circumstances this will be * overridden by the chart style). * * @since 1.2 */ public static final Color DEFAULT_LABEL_COLOR = Color.BLACK; /** * The default label offset. * * @since 1.2 */ public static final double DEFAULT_LABEL_OFFSET = 10; /** * The default tick label font (in most circumstances this will be * overridden by the chart style). * * @since 1.2 */ public static final Font DEFAULT_TICK_LABEL_FONT = new Font("Dialog", Font.PLAIN, 12); /** * The default tick label color (in most circumstances this will be * overridden by the chart style). * * @since 1.2 */ public static final Color DEFAULT_TICK_LABEL_COLOR = Color.BLACK; /** * The default stroke for the axis line. * * @since 1.2 */ public static final Stroke DEFAULT_LINE_STROKE = new BasicStroke(0f); /** * The default color for the axis line. * * @since 1.2 */ public static final Color DEFAULT_LINE_COLOR = Color.GRAY; /** A flag that determines whether or not the axis will be drawn. */ private boolean visible; /** The axis label (if {@code null}, no label is displayed). */ private String label; /** The label font (never {@code null}). */ private Font labelFont; /** The color used to draw the axis label (never {@code null}). */ private Color labelColor; /** The offset between the tick labels and the label. */ private double labelOffset; /** The stroke used to draw the axis line. */ private transient Stroke lineStroke; /** The color used to draw the axis line. */ private Color lineColor; /** Draw the tick labels? */ private boolean tickLabelsVisible; /** The font used to display tick labels (never {@code null}) */ private Font tickLabelFont; /** The tick label paint (never {@code null}). */ private Color tickLabelColor; /** Storage for registered change listeners. */ private final transient EventListenerList listenerList; /** * Creates a new label with the specified label. If the supplied label * is {@code null}, the axis will be shown without a label. * * @param label the axis label ({@code null} permitted). */ public AbstractAxis3D(String label) { this.visible = true; this.label = label; this.labelFont = DEFAULT_LABEL_FONT; this.labelColor = DEFAULT_LABEL_COLOR; this.labelOffset = DEFAULT_LABEL_OFFSET; this.lineStroke = DEFAULT_LINE_STROKE; this.lineColor = DEFAULT_LINE_COLOR; this.tickLabelsVisible = true; this.tickLabelFont = DEFAULT_TICK_LABEL_FONT; this.tickLabelColor = DEFAULT_TICK_LABEL_COLOR; this.listenerList = new EventListenerList(); } /** * Returns the flag that determines whether or not the axis is drawn * on the chart. * * @return A boolean. * * @see #setVisible(boolean) */ @Override public boolean isVisible() { return this.visible; } /** * Sets the flag that determines whether or not the axis is drawn on the * chart and sends an {@link Axis3DChangeEvent} to all registered listeners. * * @param visible the flag. * * @see #isVisible() */ @Override public void setVisible(boolean visible) { this.visible = visible; fireChangeEvent(false); } /** * Returns the axis label - the text that describes what the axis measures. * The description should usually specify the units. When this attribute * is {@code null}, the axis is drawn without a label. * * @return The axis label (possibly {@code null}). */ public String getLabel() { return this.label; } /** * Sets the axis label and sends an {@link Axis3DChangeEvent} to all * registered listeners. If the supplied label is {@code null}, * the axis will be drawn without a label. * * @param label the label ({@code null} permitted). */ public void setLabel(String label) { this.label = label; fireChangeEvent(false); } /** * Returns the font used to display the main axis label. The default value * is {@code Font("SansSerif", Font.BOLD, 12)}. * * @return The font used to display the axis label (never {@code null}). */ @Override public Font getLabelFont() { return this.labelFont; } /** * Sets the font used to display the main axis label and sends an * {@link Axis3DChangeEvent} to all registered listeners. * * @param font the new font ({@code null} not permitted). */ @Override public void setLabelFont(Font font) { Args.nullNotPermitted(font, "font"); this.labelFont = font; fireChangeEvent(false); } /** * Returns the color used for the label. The default value is * {@code Color.BLACK}. * * @return The label paint (never {@code null}). */ @Override public Color getLabelColor() { return this.labelColor; } /** * Sets the color used to draw the axis label and sends an * {@link Axis3DChangeEvent} to all registered listeners. * * @param color the color ({@code null} not permitted). */ @Override public void setLabelColor(Color color) { Args.nullNotPermitted(color, "color"); this.labelColor = color; fireChangeEvent(false); } /** * Returns the offset between the tick labels and the axis label, measured * in Java2D units. The default value is {@link #DEFAULT_LABEL_OFFSET}. * * @return The offset. * * @since 1.2 */ public double getLabelOffset() { return this.labelOffset; } /** * Sets the offset between the tick labels and the axis label and sends * an {@link Axis3DChangeEvent} to all registered listeners. * * @param offset the offset. * * @since 1.2 */ public void setLabelOffset(double offset) { this.labelOffset = offset; fireChangeEvent(false); } /** * Returns the stroke used to draw the axis line. The default value is * {@link #DEFAULT_LINE_STROKE}. * * @return The stroke used to draw the axis line (never {@code null}). */ public Stroke getLineStroke() { return this.lineStroke; } /** * Sets the stroke used to draw the axis line and sends an * {@link Axis3DChangeEvent} to all registered listeners. * * @param stroke the new stroke ({@code null} not permitted). */ public void setLineStroke(Stroke stroke) { Args.nullNotPermitted(stroke, "stroke"); this.lineStroke = stroke; fireChangeEvent(false); } /** * Returns the color used to draw the axis line. The default value is * {@link #DEFAULT_LINE_COLOR}. * * @return The color used to draw the axis line (never {@code null}). */ public Color getLineColor() { return this.lineColor; } /** * Sets the color used to draw the axis line and sends an * {@link Axis3DChangeEvent} to all registered listeners. * * @param color the new color ({@code null} not permitted). */ public void setLineColor(Color color) { Args.nullNotPermitted(color, "color"); this.lineColor = color; fireChangeEvent(false); } /** * Returns the flag that controls whether or not the tick labels are * drawn. The default value is {@code true}. * * @return A boolean. */ public boolean getTickLabelsVisible() { return this.tickLabelsVisible; } /** * Sets the flag that controls whether or not the tick labels are drawn, * and sends a change event to all registered listeners. You should think * carefully before setting this flag to {@code false}, because if * the tick labels are not shown it will be hard for the reader to * understand the resulting chart. * * @param visible visible? */ public void setTickLabelsVisible(boolean visible) { this.tickLabelsVisible = visible; fireChangeEvent(false); } /** * Returns the font used to display the tick labels. The default value * is {@link #DEFAULT_TICK_LABEL_FONT}. * * @return The font (never {@code null}). */ @Override public Font getTickLabelFont() { return this.tickLabelFont; } /** * Sets the font used to display tick labels and sends an * {@link Axis3DChangeEvent} to all registered listeners. * * @param font the font ({@code null} not permitted). */ @Override public void setTickLabelFont(Font font) { Args.nullNotPermitted(font, "font"); this.tickLabelFont = font; fireChangeEvent(false); } /** * Returns the foreground color for the tick labels. The default value * is {@link #DEFAULT_LABEL_COLOR}. * * @return The foreground color (never {@code null}). */ @Override public Color getTickLabelColor() { return this.tickLabelColor; } /** * Sets the foreground color for the tick labels and sends an * {@link Axis3DChangeEvent} to all registered listeners. * * @param color the color ({@code null} not permitted). */ @Override public void setTickLabelColor(Color color) { Args.nullNotPermitted(color, "color"); this.tickLabelColor = color; fireChangeEvent(false); } /** * Receives a {@link ChartElementVisitor}. This method is part of a general * mechanism for traversing the chart structure and performing operations * on each element in the chart. You will not normally call this method * directly. * * @param visitor the visitor ({@code null} not permitted). * * @since 1.2 */ @Override public abstract void receive(ChartElementVisitor visitor); /** * Draws the specified text as the axis label and returns a bounding * shape (2D) for the text. * * @param label the label ({@code null} not permitted). * @param g2 the graphics target ({@code null} not permitted). * @param axisLine the axis line ({@code null} not permitted). * @param opposingPt an opposing point ({@code null} not permitted). * @param offset the offset. * @param info collects rendering info ({@code null} permitted). * @param hinting perform element hinting? * * @return A bounding shape. */ protected Shape drawAxisLabel(String label, Graphics2D g2, Line2D axisLine, Point2D opposingPt, double offset, RenderingInfo info, boolean hinting) { Args.nullNotPermitted(label, "label"); Args.nullNotPermitted(g2, "g2"); Args.nullNotPermitted(axisLine, "axisLine"); Args.nullNotPermitted(opposingPt, "opposingPt"); g2.setFont(getLabelFont()); g2.setPaint(getLabelColor()); Line2D labelPosLine = Utils2D.createPerpendicularLine(axisLine, 0.5, offset, opposingPt); double theta = Utils2D.calculateTheta(axisLine); if (theta < -Math.PI / 2.0) { theta = theta + Math.PI; } if (theta > Math.PI / 2.0) { theta = theta - Math.PI; } if (hinting) { Map m = new HashMap<>(); m.put("ref", "{\"type\": \"axisLabel\", \"axis\": \"" + axisStr() + "\", \"label\": \"" + getLabel() + "\"}"); g2.setRenderingHint(Chart3DHints.KEY_BEGIN_ELEMENT, m); } Shape bounds = TextUtils.drawRotatedString(getLabel(), g2, (float) labelPosLine.getX2(), (float) labelPosLine.getY2(), TextAnchor.CENTER, theta, TextAnchor.CENTER); if (hinting) { g2.setRenderingHint(Chart3DHints.KEY_END_ELEMENT, true); } if (info != null) { RenderedElement labelElement = new RenderedElement( InteractiveElementType.AXIS_LABEL, bounds); labelElement.setProperty("axis", axisStr()); labelElement.setProperty("label", getLabel()); info.addOffsetElement(labelElement); } return bounds; } /** * Returns a string representing the configured type of the axis ("row", * "column", "value", "x", "y" or "z" - other values may be possible in the * future). A row axis on a {@link CategoryPlot3D} is in the * position of a z-axis (depth), a column axis is in the position * of an x-axis (width), a value axis is in the position of a * y-axis (height). * * @return A string (never {@code null}). * * @since 1.3 */ protected abstract String axisStr(); /** * Draws the axis along an arbitrary line (between {@code startPt} * and {@code endPt}). The opposing point is used as a reference * point to know on which side of the axis to draw the labels. * * @param g2 the graphics target ({@code null} not permitted). * @param startPt the starting point ({@code null} not permitted). * @param endPt the end point ({@code null} not permitted) * @param opposingPt an opposing point ({@code null} not permitted). * @param tickData info about the ticks to draw ({@code null} not * permitted). * @param info an object to be populated with rendering info * ({@code null} permitted). * @param hinting a flag that controls whether or not element hinting * should be performed. */ @Override public abstract void draw(Graphics2D g2, Point2D startPt, Point2D endPt, Point2D opposingPt, List tickData, RenderingInfo info, boolean hinting); /** * Tests this instance for equality with an arbitrary object. * * @param obj the object to test against ({@code null} permitted). * * @return A boolean. */ @Override public boolean equals(Object obj) { if (obj == this) { return true; } if (!(obj instanceof AbstractAxis3D)) { return false; } AbstractAxis3D that = (AbstractAxis3D) obj; if (this.visible != that.visible) { return false; } if (!ObjectUtils.equals(this.label, that.label)) { return false; } if (!this.labelFont.equals(that.labelFont)) { return false; } if (!this.labelColor.equals(that.labelColor)) { return false; } if (!this.lineStroke.equals(that.lineStroke)) { return false; } if (!this.lineColor.equals(that.lineColor)) { return false; } if (this.tickLabelsVisible != that.tickLabelsVisible) { return false; } if (!this.tickLabelFont.equals(that.tickLabelFont)) { return false; } if (!this.tickLabelColor.equals(that.tickLabelColor)) { return false; } return true; } /** * Returns a hash code for this instance. * * @return A hash code. */ @Override public int hashCode() { int hash = 5; hash = 83 * hash + (this.visible ? 1 : 0); hash = 83 * hash + ObjectUtils.hashCode(this.label); hash = 83 * hash + ObjectUtils.hashCode(this.labelFont); hash = 83 * hash + ObjectUtils.hashCode(this.labelColor); hash = 83 * hash + ObjectUtils.hashCode(this.lineStroke); hash = 83 * hash + ObjectUtils.hashCode(this.lineColor); hash = 83 * hash + (this.tickLabelsVisible ? 1 : 0); hash = 83 * hash + ObjectUtils.hashCode(this.tickLabelFont); hash = 83 * hash + ObjectUtils.hashCode(this.tickLabelColor); return hash; } /** * Registers a listener so that it will receive axis change events. * * @param listener the listener ({@code null} not permitted). */ @Override public void addChangeListener(Axis3DChangeListener listener) { this.listenerList.add(Axis3DChangeListener.class, listener); } /** * Unregisters a listener so that it will no longer receive axis * change events. * * @param listener the listener ({@code null} not permitted). */ @Override public void removeChangeListener(Axis3DChangeListener listener) { this.listenerList.remove(Axis3DChangeListener.class, listener); } /** * Notifies all registered listeners that the axis has been modified. * * @param event information about the change event. */ public void notifyListeners(Axis3DChangeEvent event) { Object[] listeners = this.listenerList.getListenerList(); for (int i = listeners.length - 2; i >= 0; i -= 2) { if (listeners[i] == Axis3DChangeListener.class) { ((Axis3DChangeListener) listeners[i + 1]).axisChanged(event); } } } /** * Sends an {@link Axis3DChangeEvent} to all registered listeners. * * @param requiresWorldUpdate a flag indicating whether this change * requires the 3D world to be updated. */ protected void fireChangeEvent(boolean requiresWorldUpdate) { notifyListeners(new Axis3DChangeEvent(this, requiresWorldUpdate)); } /** * Receives notification of a change to a marker managed by this axis - the * response is to fire a change event for the axis (to eventually trigger * a repaint of the chart). Marker changes don't require the world model * to be updated. * * @param event the event. * * @since 1.2 */ @Override public void markerChanged(MarkerChangeEvent event) { fireChangeEvent(false); } /** * Provides serialization support. * * @param stream the output stream. * * @throws IOException if there is an I/O error. */ private void writeObject(ObjectOutputStream stream) throws IOException { stream.defaultWriteObject(); SerialUtils.writeStroke(this.lineStroke, stream); } /** * Provides serialization support. * * @param stream the input stream. * * @throws IOException if there is an I/O error. * @throws ClassNotFoundException if there is a classpath problem. */ private void readObject(ObjectInputStream stream) throws IOException, ClassNotFoundException { stream.defaultReadObject(); this.lineStroke = SerialUtils.readStroke(stream); } } orson-charts-2.1.0/src/main/java/org/jfree/chart3d/axis/AbstractValueAxis3D.java000066400000000000000000000642701417331271500274020ustar00rootroot00000000000000/* =========================================================== * Orson Charts : a 3D chart library for the Java(tm) platform * =========================================================== * * (C)opyright 2013-2022, by David Gilbert. All rights reserved. * * https://github.com/jfree/orson-charts * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . * * [Oracle and Java are registered trademarks of Oracle and/or its affiliates. * Other names may be trademarks of their respective owners.] * * If you do not wish to be bound by the terms of the GPL, an alternative * commercial license can be purchased. For details, please see visit the * Orson Charts home page: * * http://www.object-refinery.com/orsoncharts/index.html * */ package org.jfree.chart3d.axis; import java.awt.BasicStroke; import java.awt.Color; import java.awt.Paint; import java.awt.Stroke; import java.io.IOException; import java.io.ObjectInputStream; import java.io.ObjectOutputStream; import java.io.Serializable; import java.util.ArrayList; import java.util.LinkedHashMap; import java.util.List; import java.util.Map; import org.jfree.chart3d.internal.Args; import org.jfree.chart3d.internal.ObjectUtils; import org.jfree.chart3d.internal.SerialUtils; import org.jfree.chart3d.ChartElementVisitor; import org.jfree.chart3d.data.Range; import org.jfree.chart3d.data.category.CategoryDataset3D; import org.jfree.chart3d.marker.MarkerData; import org.jfree.chart3d.marker.NumberMarker; import org.jfree.chart3d.marker.RangeMarker; import org.jfree.chart3d.marker.ValueMarker; import org.jfree.chart3d.plot.CategoryPlot3D; import org.jfree.chart3d.plot.XYZPlot; /** * A base class for implementing numerical axes. *

* NOTE: This class is serializable, but the serialization format is subject * to change in future releases and should not be relied upon for persisting * instances of this class. */ @SuppressWarnings("serial") public abstract class AbstractValueAxis3D extends AbstractAxis3D implements ValueAxis3D, Serializable{ /** The type of use for which the axis has been configured. */ private ValueAxis3DType configuredType; /** The axis range. */ protected Range range; private boolean inverted; /** * A flag that controls whether or not the axis range is automatically * adjusted to display all of the data items in the dataset. */ private boolean autoAdjustRange; /** The percentage margin to leave at the lower end of the axis. */ private double lowerMargin; /** The percentage margin to leave at the upper end of the axis. */ private double upperMargin; /** * The default range to apply when there is no data in the dataset and the * autoAdjustRange flag is true. A sensible default is going to depend on * the context, so the user should change it as necessary. */ private Range defaultAutoRange; /** * The minimum length for the axis range when auto-calculated. This will * be applied, for example, when the dataset contains just a single value. */ private double minAutoRangeLength; /** The tick label offset (number of Java2D units). */ private double tickLabelOffset; /** The length of tick marks (in Java2D units). Can be set to 0.0. */ private double tickMarkLength; /** The tick mark stroke (never {@code null}). */ private transient Stroke tickMarkStroke; /** The tick mark paint (never {@code null}). */ private transient Paint tickMarkPaint; /** The orientation for the tick labels. */ private LabelOrientation tickLabelOrientation; /** The tick label factor (defaults to 1.4). */ private double tickLabelFactor; /** Storage for value markers for the axis (empty by default). */ private final Map valueMarkers; /** * Creates a new axis instance. * * @param label the axis label ({@code null} permitted). * @param range the axis range ({@code null} not permitted). */ public AbstractValueAxis3D(String label, Range range) { super(label); Args.nullNotPermitted(range, "range"); this.configuredType = null; this.range = range; this.autoAdjustRange = true; this.lowerMargin = 0.05; this.upperMargin = 0.05; this.defaultAutoRange = new Range(0.0, 1.0); this.minAutoRangeLength = 0.001; this.tickLabelOffset = 5.0; this.tickLabelOrientation = LabelOrientation.PARALLEL; this.tickLabelFactor = 1.4; this.tickMarkLength = 3.0; this.tickMarkStroke = new BasicStroke(0.5f); this.tickMarkPaint = Color.GRAY; this.valueMarkers = new LinkedHashMap<>(); } /** * Returns the configured type for the axis. * * @return The configured type ({@code null} if the axis has not yet * been assigned to a plot). * * @since 1.3 */ @Override public ValueAxis3DType getConfiguredType() { return this.configuredType; } /** * Returns a string representing the configured type of the axis. * * @return A string. */ @Override protected String axisStr() { if (this.configuredType == null) { return ""; } if (this.configuredType.equals(ValueAxis3DType.VALUE)) { return "value"; } if (this.configuredType.equals(ValueAxis3DType.X)) { return "x"; } if (this.configuredType.equals(ValueAxis3DType.Y)) { return "y"; } if (this.configuredType.equals(ValueAxis3DType.Z)) { return "z"; } return ""; } /** * Returns the axis range. You can set the axis range manually or you can * rely on the autoAdjustRange feature to set the axis range to match * the data being plotted. * * @return the axis range (never {@code null}). */ @Override public Range getRange() { return this.range; } /** * Sets the axis range (bounds) and sends an {@link Axis3DChangeEvent} to * all registered listeners. * * @param range the new range (must have positive length and * {@code null} is not permitted). */ @Override public void setRange(Range range) { Args.nullNotPermitted(range, "range"); if (range.getLength() <= 0.0) { throw new IllegalArgumentException( "Requires a range with length > 0"); } this.range = range; this.autoAdjustRange = false; fireChangeEvent(true); } /** * Updates the axis range (used by the auto-range calculation) without * notifying listeners. * * @param range the new range. */ protected void updateRange(Range range) { this.range = range; } /** * Sets the axis range and sends an {@link Axis3DChangeEvent} to all * registered listeners. * * @param min the lower bound for the range (requires min < max). * @param max the upper bound for the range (requires max > min). */ @Override public void setRange(double min, double max) { setRange(new Range(min, max)); } /** * Returns the flag that controls whether or not the axis range is * automatically updated in response to dataset changes. The default * value is {@code true}. * * @return A boolean. */ public boolean isAutoAdjustRange() { return this.autoAdjustRange; } /** * Sets the flag that controls whether or not the axis range is * automatically updated in response to dataset changes, and sends an * {@link Axis3DChangeEvent} to all registered listeners. * * @param autoAdjust the new flag value. */ public void setAutoAdjustRange(boolean autoAdjust) { this.autoAdjustRange = autoAdjust; fireChangeEvent(true); } /** * Returns the size of the lower margin that is added by the auto-range * calculation, as a percentage of the data range. This margin is used to * prevent data items from being plotted right at the edges of the chart. * The default value is {@code 0.05} (five percent). * * @return The lower margin. */ public double getLowerMargin() { return this.lowerMargin; } /** * Sets the size of the lower margin that will be added by the auto-range * calculation and sends an {@link Axis3DChangeEvent} to all registered * listeners. * * @param margin the margin as a percentage of the data range * (0.05 = five percent). * * @see #setUpperMargin(double) */ public void setLowerMargin(double margin) { this.lowerMargin = margin; fireChangeEvent(true); } /** * Returns the size of the upper margin that is added by the auto-range * calculation, as a percentage of the data range. This margin is used to * prevent data items from being plotted right at the edges of the chart. * The default value is {@code 0.05} (five percent). * * @return The upper margin. */ public double getUpperMargin() { return this.upperMargin; } /** * Sets the size of the upper margin that will be added by the auto-range * calculation and sends an {@link Axis3DChangeEvent} to all registered * listeners. * * @param margin the margin as a percentage of the data range * (0.05 = five percent). * * @see #setLowerMargin(double) */ public void setUpperMargin(double margin) { this.upperMargin = margin; fireChangeEvent(true); } /** * Returns the default range used when the {@code autoAdjustRange} * flag is {@code true} but the dataset contains no values. The * default range is {@code (0.0 to 1.0)}, depending on the context * you may want to change this. * * @return The default range (never {@code null}). * * @see #setDefaultAutoRange(Range) */ public Range getDefaultAutoRange() { return this.defaultAutoRange; } /** * Sets the default range used when the {@code autoAdjustRange} * flag is {@code true} but the dataset contains no values, and sends * an {@link Axis3DChangeEvent} to all registered listeners. * * @param range the range ({@code null} not permitted). * * @see #getDefaultAutoRange() */ public void setDefaultAutoRange(Range range) { Args.nullNotPermitted(range, "range"); this.defaultAutoRange = range; fireChangeEvent(true); } /** * Returns the minimum length for the axis range when auto-calculated. * The default value is 0.001. * * @return The minimum length. * * @since 1.4 */ public double getMinAutoRangeLength() { return this.minAutoRangeLength; } /** * Sets the minimum length for the axis range when it is auto-calculated * and sends a change event to all registered listeners. * * @param length the new minimum length. * * @since 1.4 */ public void setMinAutoRangeLength(double length) { Args.positiveRequired(length, "length"); this.minAutoRangeLength = length; fireChangeEvent(this.range.getLength() < length); } /** * Returns the flag that determines whether or not the order of values on * the axis is inverted. The default value is {@code false}. * * @return A boolean. * * @since 1.5 */ @Override public boolean isInverted() { return this.inverted; } /** * Sets the flag that determines whether or not the order of values on the * axis is inverted, and sends an {@link Axis3DChangeEvent} to all * registered listeners. * * @param inverted the new flag value. * * @since 1.5 */ @Override public void setInverted(boolean inverted) { this.inverted = inverted; fireChangeEvent(true); } /** * Returns the orientation for the tick labels. The default value is * {@link LabelOrientation#PARALLEL}. * * @return The orientation for the tick labels (never {@code null}). * * @since 1.2 */ public LabelOrientation getTickLabelOrientation() { return this.tickLabelOrientation; } /** * Sets the orientation for the tick labels and sends a change event to * all registered listeners. In general, {@code PARALLEL} is the * best setting for X and Z axes, and {@code PERPENDICULAR} is the * best setting for Y axes. * * @param orientation the orientation ({@code null} not permitted). * * @since 1.2 */ public void setTickLabelOrientation(LabelOrientation orientation) { Args.nullNotPermitted(orientation, "orientation"); this.tickLabelOrientation = orientation; fireChangeEvent(false); } /** * Returns the tick label factor, a multiplier for the label height to * determine the maximum number of tick labels that can be displayed. * The default value is {@code 1.4}. * * @return The tick label factor. */ public double getTickLabelFactor() { return this.tickLabelFactor; } /** * Sets the tick label factor and sends an {@link Axis3DChangeEvent} * to all registered listeners. This should be at least 1.0, higher values * will result in larger gaps between the tick marks. * * @param factor the factor. */ public void setTickLabelFactor(double factor) { this.tickLabelFactor = factor; fireChangeEvent(false); } /** * Returns the tick label offset, the gap between the tick marks and the * tick labels (in Java2D units). The default value is {@code 5.0}. * * @return The tick label offset. */ public double getTickLabelOffset() { return this.tickLabelOffset; } /** * Sets the tick label offset and sends an {@link Axis3DChangeEvent} to * all registered listeners. * * @param offset the offset. */ public void setTickLabelOffset(double offset) { this.tickLabelOffset = offset; } /** * Returns the length of the tick marks (in Java2D units). The default * value is {@code 3.0}. * * @return The length of the tick marks. */ public double getTickMarkLength() { return this.tickMarkLength; } /** * Sets the length of the tick marks and sends an {@link Axis3DChangeEvent} * to all registered listeners. You can set this to {@code 0.0} if * you prefer no tick marks to be displayed on the axis. * * @param length the length (in Java2D units). */ public void setTickMarkLength(double length) { this.tickMarkLength = length; fireChangeEvent(false); } /** * Returns the stroke used to draw the tick marks. The default value is * {@code BasicStroke(0.5f)}. * * @return The tick mark stroke (never {@code null}). */ public Stroke getTickMarkStroke() { return this.tickMarkStroke; } /** * Sets the stroke used to draw the tick marks and sends an * {@link Axis3DChangeEvent} to all registered listeners. * * @param stroke the stroke ({@code null} not permitted). */ public void setTickMarkStroke(Stroke stroke) { Args.nullNotPermitted(stroke, "stroke"); this.tickMarkStroke = stroke; fireChangeEvent(false); } /** * Returns the paint used to draw the tick marks. The default value is * {@code Color.GRAY}. * * @return The tick mark paint (never {@code null}). */ public Paint getTickMarkPaint() { return this.tickMarkPaint; } /** * Sets the paint used to draw the tick marks and sends an * {@link Axis3DChangeEvent} to all registered listeners. * * @param paint the paint ({@code null} not permitted). */ public void setTickMarkPaint(Paint paint) { Args.nullNotPermitted(paint, "paint"); this.tickMarkPaint = paint; fireChangeEvent(false); } /** * Configures the axis to be used as the value axis for the specified * plot. This method is used internally, you should not need to call it * directly. * * @param plot the plot ({@code null} not permitted). */ @Override @SuppressWarnings("unchecked") public void configureAsValueAxis(CategoryPlot3D plot) { this.configuredType = ValueAxis3DType.VALUE; if (this.autoAdjustRange) { CategoryDataset3D dataset = plot.getDataset(); Range valueRange = plot.getRenderer().findValueRange(dataset); if (valueRange != null) { updateRange(adjustedDataRange(valueRange)); } else { updateRange(this.defaultAutoRange); } } } /** * Configures the axis to be used as the x-axis for the specified plot. * This method is used internally, you should not need to call it * directly. * * @param plot the plot ({@code null} not permitted). */ @Override public void configureAsXAxis(XYZPlot plot) { this.configuredType = ValueAxis3DType.X; if (this.autoAdjustRange) { Range xRange = plot.getRenderer().findXRange(plot.getDataset()); if (xRange != null) { updateRange(adjustedDataRange(xRange)); } else { updateRange(this.defaultAutoRange); } } } /** * Configures the axis to be used as the y-axis for the specified plot. * This method is used internally, you should not need to call it * directly. * * @param plot the plot ({@code null} not permitted). */ @Override public void configureAsYAxis(XYZPlot plot) { this.configuredType = ValueAxis3DType.Y; if (this.autoAdjustRange) { Range yRange = plot.getRenderer().findYRange(plot.getDataset()); if (yRange != null) { updateRange(adjustedDataRange(yRange)); } else { updateRange(this.defaultAutoRange); } } } /** * Configures the axis to be used as the z-axis for the specified plot. * This method is used internally, you should not need to call it * directly. * * @param plot the plot ({@code null} not permitted). */ @Override public void configureAsZAxis(XYZPlot plot) { this.configuredType = ValueAxis3DType.Z; if (this.autoAdjustRange) { Range zRange = plot.getRenderer().findZRange(plot.getDataset()); if (zRange != null) { updateRange(adjustedDataRange(zRange)); } else { updateRange(this.defaultAutoRange); } } } /** * Adjusts the range by adding the lower and upper margins and taking into * account any other settings. * * @param range the range ({@code null} not permitted). * * @return The adjusted range. */ protected abstract Range adjustedDataRange(Range range); /** * Returns the marker with the specified key, if there is one. * * @param key the key ({@code null} not permitted). * * @return The marker (possibly {@code null}). * * @since 1.2 */ @Override public ValueMarker getMarker(String key) { return this.valueMarkers.get(key); } /** * Sets the marker for the specified key and sends a change event to * all registered listeners. If there is an existing marker it is replaced * (the axis will no longer listen for change events on the previous * marker). * * @param key the key that identifies the marker ({@code null} not * permitted). * @param marker the marker ({@code null} permitted). * * @since 1.2 */ public void setMarker(String key, ValueMarker marker) { ValueMarker existing = this.valueMarkers.get(key); if (existing != null) { existing.removeChangeListener(this); } this.valueMarkers.put(key, marker); marker.addChangeListener(this); fireChangeEvent(false); } /** * Returns a new map containing the markers assigned to this axis. * * @return A map. * * @since 1.2 */ public Map getMarkers() { return new LinkedHashMap<>(this.valueMarkers); } /** * Generates and returns a list of marker data items for the axis. * * @return A list of marker data items (never {@code null}). */ @Override public List generateMarkerData() { List result = new ArrayList<>(); Range range = getRange(); for (Map.Entry entry : this.valueMarkers.entrySet()) { ValueMarker vm = entry.getValue(); if (range.intersects(vm.getRange())) { MarkerData markerData; if (vm instanceof NumberMarker) { NumberMarker nm = (NumberMarker) vm; markerData = new MarkerData(entry.getKey(), range.percent(nm.getValue())); markerData.setLabelAnchor(nm.getLabel() != null ? nm.getLabelAnchor() : null); } else if (vm instanceof RangeMarker) { RangeMarker rm = (RangeMarker) vm; double startValue = rm.getStart().getValue(); boolean startPegged = false; if (!range.contains(startValue)) { startValue = range.peggedValue(startValue); startPegged = true; } double startPos = range.percent(startValue); double endValue = rm.getEnd().getValue(); boolean endPegged = false; if (!range.contains(endValue)) { endValue = range.peggedValue(endValue); endPegged = true; } double endPos = range.percent(endValue); markerData = new MarkerData(entry.getKey(), startPos, startPegged, endPos, endPegged); markerData.setLabelAnchor(rm.getLabel() != null ? rm.getLabelAnchor() : null); } else { throw new RuntimeException("Unrecognised marker."); } result.add(markerData); } } return result; } /** * Receives a {@link ChartElementVisitor}. This method is part of a general * mechanism for traversing the chart structure and performing operations * on each element in the chart. You will not normally call this method * directly. * * @param visitor the visitor ({@code null} not permitted). * * @since 1.2 */ @Override public void receive(ChartElementVisitor visitor) { for (ValueMarker marker : this.valueMarkers.values()) { marker.receive(visitor); } visitor.visit(this); } @Override public boolean equals(Object obj) { if (obj == this) { return true; } if (!(obj instanceof AbstractValueAxis3D)) { return false; } AbstractValueAxis3D that = (AbstractValueAxis3D) obj; if (!this.range.equals(that.range)) { return false; } if (this.autoAdjustRange != that.autoAdjustRange) { return false; } if (this.lowerMargin != that.lowerMargin) { return false; } if (this.upperMargin != that.upperMargin) { return false; } if (!this.defaultAutoRange.equals(that.defaultAutoRange)) { return false; } if (this.tickLabelOffset != that.tickLabelOffset) { return false; } if (this.tickLabelFactor != that.tickLabelFactor) { return false; } if (!this.tickLabelOrientation.equals(that.tickLabelOrientation)) { return false; } if (this.tickMarkLength != that.tickMarkLength) { return false; } if (!ObjectUtils.equalsPaint(this.tickMarkPaint, that.tickMarkPaint)) { return false; } if (!this.tickMarkStroke.equals(that.tickMarkStroke)) { return false; } return super.equals(obj); } /** * Provides serialization support. * * @param stream the output stream. * * @throws IOException if there is an I/O error. */ private void writeObject(ObjectOutputStream stream) throws IOException { stream.defaultWriteObject(); SerialUtils.writePaint(this.tickMarkPaint, stream); SerialUtils.writeStroke(this.tickMarkStroke, stream); } /** * Provides serialization support. * * @param stream the input stream. * * @throws IOException if there is an I/O error. * @throws ClassNotFoundException if there is a classpath problem. */ private void readObject(ObjectInputStream stream) throws IOException, ClassNotFoundException { stream.defaultReadObject(); this.tickMarkPaint = SerialUtils.readPaint(stream); this.tickMarkStroke = SerialUtils.readStroke(stream); } } orson-charts-2.1.0/src/main/java/org/jfree/chart3d/axis/Axis3D.java000066400000000000000000000165071417331271500247210ustar00rootroot00000000000000/* =========================================================== * Orson Charts : a 3D chart library for the Java(tm) platform * =========================================================== * * (C)opyright 2013-2022, by David Gilbert. All rights reserved. * * https://github.com/jfree/orson-charts * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . * * [Oracle and Java are registered trademarks of Oracle and/or its affiliates. * Other names may be trademarks of their respective owners.] * * If you do not wish to be bound by the terms of the GPL, an alternative * commercial license can be purchased. For details, please see visit the * Orson Charts home page: * * http://www.object-refinery.com/orsoncharts/index.html * */ package org.jfree.chart3d.axis; import java.awt.Color; import java.awt.Graphics2D; import java.awt.geom.Point2D; import java.awt.Font; import java.util.List; import org.jfree.chart3d.ChartElement; import org.jfree.chart3d.data.Range; import org.jfree.chart3d.graphics3d.RenderingInfo; /** * An interface that must be supported by axes for 3D plots. */ public interface Axis3D extends ChartElement { /** * Returns the flag that determines whether or not the axis is drawn * on the chart. * * @return A boolean. * * @see #setVisible(boolean) */ boolean isVisible(); /** * Sets the flag that determines whether or not the axis is drawn on the * chart and sends an {@link Axis3DChangeEvent} to all registered listeners. * * @param visible the flag. * * @see #isVisible() */ void setVisible(boolean visible); /** * Returns the font that is used to display the main axis label. * * @return The font (never {@code null}). */ Font getLabelFont(); /** * Sets the font for the axis label (the main label, not the tick labels) * and sends an {@link Axis3DChangeEvent} to all registered listeners. * * @param font the font ({@code null} not permitted). */ void setLabelFont(Font font); /** * Returns the color used to draw the axis label. * * @return The color (never {@code null}). * * @since 1.2 */ Color getLabelColor(); /** * Sets the color used to draw the axis label and sends an * {@link Axis3DChangeEvent} to all registered listeners. * * @param color the color ({@code null} not permitted). * * @since 1.2 */ void setLabelColor(Color color); /** * Returns the font that is used to display the tick labels. * * @return The font (never {@code null}). */ Font getTickLabelFont(); /** * Sets the font for the tick labels and sends an {@link Axis3DChangeEvent} * to all registered listeners. * * @param font the font ({@code null} not permitted). */ void setTickLabelFont(Font font); /** * Returns the color used to draw the axis tick labels. * * @return The color (never {@code null}). * * @since 1.2 */ Color getTickLabelColor(); /** * Sets the color used to draw the axis tick labels and sends an * {@link Axis3DChangeEvent} to all registered listeners. * * @param color the color ({@code null} not permitted). * * @since 1.2 */ void setTickLabelColor(Color color); /** * Returns the axis range (the minimum and maximum values displayed on * the axis). Note that even categorical axes will have a range, although * since numerical values are not displayed the range is often set to * {@code (0.0, 1.0)} for convenience. * * @return The axis range (never {@code null}). */ Range getRange(); /** * Sets the axis range and sends an {@link Axis3DChangeEvent} to all * registered listeners. * * @param range the range ({@code null} not permitted). */ void setRange(Range range); /** * Sets the axis range and sends an {@link Axis3DChangeEvent} to all * registered listeners. * * @param min the lower bound for the axis. * @param max the upper bound for the axis. */ void setRange(double min, double max); /** * Returns the flag that determines whether or not the order of values on * the axis is inverted. The default value is {@code false}. * * @return A boolean. * * @since 1.5 */ boolean isInverted(); /** * Sets the flag that determines whether or not the order of values on the * axis is inverted, and sends an {@link Axis3DChangeEvent} to all * registered listeners. * * @param inverted the new flag value. * * @since 1.5 */ void setInverted(boolean inverted); /** * Translates a data value to a world coordinate. Since we draw the charts * in a box that has one corner at {@code (0, 0, 0)}, we only need to * know the length of the side of the box along which we are translating in * order to do the calculation. * * @param value the data value. * @param length the box side length. * * @return The translated value. */ double translateToWorld(double value, double length); /** * Draws the axis along an arbitrary line (between {@code startPt} * and {@code endPt}). The opposing point is used as a reference * point to know on which side of the axis to draw the labels. * * @param g2 the graphics target ({@code null} not permitted). * @param startPt the starting point ({@code null} not permitted). * @param endPt the end point ({@code null} not permitted) * @param opposingPt an opposing point ({@code null} not permitted). * @param tickData info about the ticks to draw ({@code null} not * permitted). * @param info an object to be populated with rendering info * ({@code null} permitted). * @param hinting a flag that controls whether or not element hinting * should be performed. * * @since 1.3 */ void draw(Graphics2D g2, Point2D startPt, Point2D endPt, Point2D opposingPt, List tickData, RenderingInfo info, boolean hinting); /** * Registers a listener so that it receives notification of changes to the * axis. * * @param listener the listener ({@code null} not permitted). */ void addChangeListener(Axis3DChangeListener listener); /** * Deregisters a listener so that it no longer receives notification of * changes to the axis. * * @param listener the listener ({@code null} not permitted). */ void removeChangeListener(Axis3DChangeListener listener); } orson-charts-2.1.0/src/main/java/org/jfree/chart3d/axis/Axis3DChangeEvent.java000066400000000000000000000071131417331271500270220ustar00rootroot00000000000000/* =========================================================== * Orson Charts : a 3D chart library for the Java(tm) platform * =========================================================== * * (C)opyright 2013-2022, by David Gilbert. All rights reserved. * * https://github.com/jfree/orson-charts * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . * * [Oracle and Java are registered trademarks of Oracle and/or its affiliates. * Other names may be trademarks of their respective owners.] * * If you do not wish to be bound by the terms of the GPL, an alternative * commercial license can be purchased. For details, please see visit the * Orson Charts home page: * * http://www.object-refinery.com/orsoncharts/index.html * */ package org.jfree.chart3d.axis; import java.util.EventObject; import org.jfree.chart3d.internal.Args; /** * An event associated with a change to an {@link Axis3D}. These change * events will be generated by an axis and broadcast to the plot that owns the * axis (in the standard setup, the plot will then trigger its own change event * to notify the chart that a subcomponent of the plot has changed). *

* NOTE: This class is serializable, but the serialization format is subject * to change in future releases and should not be relied upon for persisting * instances of this class. */ @SuppressWarnings("serial") public class Axis3DChangeEvent extends EventObject { /** The axis associated with this event. */ private Axis3D axis; /** * A flag indicating whether or not the change requires the 3D world to * be updated. */ private boolean requiresWorldUpdate; /** * Creates a new event. * * @param axis the axis ({@code null} not permitted). * @param requiresWorldUpdate a flag indicating whether or not this change * requires the 3D world to be updated. */ public Axis3DChangeEvent(Axis3D axis, boolean requiresWorldUpdate) { this(axis, axis, requiresWorldUpdate); } /** * Creates a new event. * * @param source the event source. * @param axis the axis ({@code null} not permitted). * @param requiresWorldUpdate a flag indicating whether or not this change * requires the 3D world to be updated. */ public Axis3DChangeEvent(Object source, Axis3D axis, boolean requiresWorldUpdate) { super(source); Args.nullNotPermitted(axis, "axis"); this.axis = axis; this.requiresWorldUpdate = requiresWorldUpdate; } /** * Returns the axis associated with this event. * * @return The axis (never {@code null}). */ public Axis3D getAxis() { return this.axis; } /** * Returns the flag that indicates whether or not this change will require * the 3D world to be updated. * * @return A boolean. * * @since 1.2 */ public boolean requiresWorldUpdate() { return this.requiresWorldUpdate; } } orson-charts-2.1.0/src/main/java/org/jfree/chart3d/axis/Axis3DChangeListener.java000066400000000000000000000037061417331271500275320ustar00rootroot00000000000000/* =========================================================== * Orson Charts : a 3D chart library for the Java(tm) platform * =========================================================== * * (C)opyright 2013-2022, by David Gilbert. All rights reserved. * * https://github.com/jfree/orson-charts * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . * * [Oracle and Java are registered trademarks of Oracle and/or its affiliates. * Other names may be trademarks of their respective owners.] * * If you do not wish to be bound by the terms of the GPL, an alternative * commercial license can be purchased. For details, please see visit the * Orson Charts home page: * * http://www.object-refinery.com/orsoncharts/index.html * */ package org.jfree.chart3d.axis; import java.util.EventListener; import org.jfree.chart3d.plot.CategoryPlot3D; import org.jfree.chart3d.plot.XYZPlot; /** * A listener for axis change events. The plot classes that have axes * ({@link CategoryPlot3D} and {@link XYZPlot}) implement this interface so * that they can receive notification when the axes are modified. */ public interface Axis3DChangeListener extends EventListener { /** * Called to inform that an axis change event has occurred. * * @param event the event ({@code null} not permitted). */ void axisChanged(Axis3DChangeEvent event); } orson-charts-2.1.0/src/main/java/org/jfree/chart3d/axis/CategoryAxis3D.java000066400000000000000000000123331417331271500264100ustar00rootroot00000000000000/* =========================================================== * Orson Charts : a 3D chart library for the Java(tm) platform * =========================================================== * * (C)opyright 2013-2022, by David Gilbert. All rights reserved. * * https://github.com/jfree/orson-charts * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . * * [Oracle and Java are registered trademarks of Oracle and/or its affiliates. * Other names may be trademarks of their respective owners.] * * If you do not wish to be bound by the terms of the GPL, an alternative * commercial license can be purchased. For details, please see visit the * Orson Charts home page: * * http://www.object-refinery.com/orsoncharts/index.html * */ package org.jfree.chart3d.axis; import java.util.List; import org.jfree.chart3d.data.category.CategoryDataset3D; import org.jfree.chart3d.marker.CategoryMarker; import org.jfree.chart3d.marker.MarkerData; import org.jfree.chart3d.plot.CategoryPlot3D; /** * An axis that displays categories and is used with a {@link CategoryPlot3D} * for the row and column axes. Most of the methods in this interface are * intended to be called by the plot that the axis is assigned to, they won't * normally be called by external code. */ public interface CategoryAxis3D extends Axis3D { /** * Returns {@code true} if this axis is being used as the row axis * in a plot, and {@code false} otherwise. * * @return A boolean. * * @since 1.3 */ boolean isRowAxis(); /** * Returns {@code true} if this axis is being used as the column axis * in a plot, and {@code false} otherwise. * * @return A boolean. * * @since 1.3 */ boolean isColumnAxis(); /** * Configure the axis as a row axis for the specified plot. Note that this * method will be called by the plot, it will not normally be called by * external code. * * @param plot the plot ({@code null} not permitted). */ void configureAsRowAxis(CategoryPlot3D plot); /** * Configure the axis as a column axis for the specified plot. Note that * this method will be called by the plot, it will not normally be called * by external code. * * @param plot the plot ({@code null} not permitted). */ void configureAsColumnAxis(CategoryPlot3D plot); /** * Returns the width of a single category in units corresponding to * the current axis range. * * @return The width of a single category. */ double getCategoryWidth(); /** * Returns the numerical value along the axis that corresponds to the * specified category. If the category is unknown, this method will * return {@code Double.NaN}. * * @param category the category ({@code null} not permitted). * * @return The axis value. */ double getCategoryValue(Comparable category); /** * Generates the tick data for the axis (assumes the axis is being used * as the row axis). The dataset is passed as an argument to provide the * opportunity to incorporate dataset-specific info into tick labels (for * example, a row label might show the total for that row in the dataset) * ---whether or not this is used depends on the axis implementation. * * @param dataset the dataset ({@code null} not permitted). * * @return The tick data. * * @since 1.2 */ List generateTickDataForRows(CategoryDataset3D dataset); /** * Generates the tick data for the axis (assumes the axis is being used * as the row axis). The dataset is passed as an argument to provide the * opportunity to incorporate dataset-specific info into tick labels (for * example, a row label might show the total for that row in the dataset) * ---whether or not this is used depends on the axis implementation. * * @param dataset the dataset ({@code null} not permitted). * * @return The tick data. * * @since 1.2 */ List generateTickDataForColumns(CategoryDataset3D dataset); /** * Returns a list of marker data instances for the markers that fall * within the current axis range. * * @return A list of marker data. */ List generateMarkerData(); /** * Returns the marker with the specified key, if there is one. * * @param key the key ({@code null} not permitted). * * @return The marker (possibly {@code null}). * * @since 1.2 */ CategoryMarker getMarker(String key); } orson-charts-2.1.0/src/main/java/org/jfree/chart3d/axis/IntegerTickSelector.java000066400000000000000000000125561417331271500275370ustar00rootroot00000000000000/* =========================================================== * Orson Charts : a 3D chart library for the Java(tm) platform * =========================================================== * * (C)opyright 2013-2022, by David Gilbert. All rights reserved. * * https://github.com/jfree/orson-charts * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . * * [Oracle and Java are registered trademarks of Oracle and/or its affiliates. * Other names may be trademarks of their respective owners.] * * If you do not wish to be bound by the terms of the GPL, an alternative * commercial license can be purchased. For details, please see visit the * Orson Charts home page: * * http://www.object-refinery.com/orsoncharts/index.html * */ package org.jfree.chart3d.axis; import java.io.Serializable; import java.text.DecimalFormat; import java.text.Format; import org.jfree.chart3d.internal.Args; /** * A {@link TickSelector} implementation that selects tick units in multiples * of 1, 2 and 5 and only displays integer values. *

* NOTE: This class is serializable, but the serialization format is subject * to change in future releases and should not be relied upon for persisting * instances of this class. * * @since 1.5 */ @SuppressWarnings("serial") public class IntegerTickSelector implements TickSelector, Serializable { private int power = 0; private int factor = 1; /** * Creates a new instance. */ public IntegerTickSelector() { this.power = 0; this.factor = 1; } /** * Selects and returns a standard tick size that is greater than or equal to * the specified reference value and, ideally, as close to it as possible * (to minimise the number of iterations used by axes to determine the tick * size to use). After a call to this method, the * {@link #getCurrentTickSize()} method should return the selected tick * size (there is a "pointer" to this tick size), the {@link #next()} * method should move the pointer to the next (larger) standard tick size, * and the {@link #previous()} method should move the pointer to the * previous (smaller) standard tick size. * * @param reference the reference value (must be positive and finite). * * @return The selected tick size. */ @Override public double select(double reference) { Args.finitePositiveRequired(reference, "reference"); this.power = (int) Math.ceil(Math.log10(reference)); this.factor = 1; return getCurrentTickSize(); } /** * Move the cursor to the next (larger) tick size, if there is one. * Returns {@code true} in the case that the cursor is moved, and * {@code false} where there are a finite number of tick sizes and the * current tick size is the largest available. */ @Override public boolean next() { if (factor == 1) { factor = 2; return true; } if (factor == 2) { factor = 5; return true; } if (factor == 5) { power++; factor = 1; return true; } throw new IllegalStateException("We should never get here."); } /** * Move the cursor to the previous (smaller) tick size, if there is one. * Returns {@code true} in the case that the cursor is moved, and * {@code false} where there are a finite number of tick sizes and the * current tick size is the smallest available. */ @Override public boolean previous() { if (factor == 1) { if (power == 0) { return false; } factor = 5; power--; return true; } if (factor == 2) { factor = 1; return true; } if (factor == 5) { factor = 2; return true; } throw new IllegalStateException("We should never get here."); } @Override public double getCurrentTickSize() { return this.factor * Math.pow(10.0, this.power); } private final DecimalFormat df0 = new DecimalFormat("#,##0"); @Override public Format getCurrentTickLabelFormat() { if (power >= 0 && power <= 6) { return df0; } return new DecimalFormat("0.0000E0"); } /** * Tests this instance for equality with an arbitrary object. * * @param obj the object ({@code null} permitted). * * @return A boolean. */ @Override public boolean equals(Object obj) { if (obj == this) { return true; } if (!(obj instanceof IntegerTickSelector)) { return false; } return true; } } orson-charts-2.1.0/src/main/java/org/jfree/chart3d/axis/LabelOrientation.java000066400000000000000000000031541417331271500270530ustar00rootroot00000000000000/* =========================================================== * Orson Charts : a 3D chart library for the Java(tm) platform * =========================================================== * * (C)opyright 2013-2022, by David Gilbert. All rights reserved. * * https://github.com/jfree/orson-charts * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . * * [Oracle and Java are registered trademarks of Oracle and/or its affiliates. * Other names may be trademarks of their respective owners.] * * If you do not wish to be bound by the terms of the GPL, an alternative * commercial license can be purchased. For details, please see visit the * Orson Charts home page: * * http://www.object-refinery.com/orsoncharts/index.html * */ package org.jfree.chart3d.axis; /** * The orientation of an axis label relative to the axis. */ public enum LabelOrientation { /** Labels are drawn perpendicular to the axis line. */ PERPENDICULAR, /** Labels are drawn parallel to the axis line. */ PARALLEL } orson-charts-2.1.0/src/main/java/org/jfree/chart3d/axis/LogAxis3D.java000066400000000000000000000646701417331271500253670ustar00rootroot00000000000000/* =========================================================== * Orson Charts : a 3D chart library for the Java(tm) platform * =========================================================== * * (C)opyright 2013-2022, by David Gilbert. All rights reserved. * * https://github.com/jfree/orson-charts * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . * * [Oracle and Java are registered trademarks of Oracle and/or its affiliates. * Other names may be trademarks of their respective owners.] * * If you do not wish to be bound by the terms of the GPL, an alternative * commercial license can be purchased. For details, please see visit the * Orson Charts home page: * * http://www.object-refinery.com/orsoncharts/index.html * */ package org.jfree.chart3d.axis; import java.awt.FontMetrics; import java.awt.Graphics2D; import java.awt.font.TextAttribute; import java.awt.font.TextLayout; import java.awt.geom.Line2D; import java.awt.geom.Point2D; import java.awt.geom.Rectangle2D; import java.text.AttributedString; import java.text.DecimalFormat; import java.text.Format; import java.text.NumberFormat; import java.util.ArrayList; import java.util.List; import java.util.HashMap; import java.util.Map; import org.jfree.chart3d.Chart3DHints; import org.jfree.chart3d.data.Range; import org.jfree.chart3d.graphics2d.TextAnchor; import org.jfree.chart3d.graphics3d.RenderingInfo; import org.jfree.chart3d.graphics3d.internal.Utils2D; import org.jfree.chart3d.internal.Args; import org.jfree.chart3d.internal.ObjectUtils; import org.jfree.chart3d.internal.TextUtils; /** * A numerical axis with a logarithmic scale. *

* NOTE: This class is serializable, but the serialization format is subject * to change in future releases and should not be relied upon for persisting * instances of this class. * * @since 1.2 */ @SuppressWarnings("serial") public class LogAxis3D extends AbstractValueAxis3D implements ValueAxis3D { /** The default value for the smallest value attribute. */ public static final double DEFAULT_SMALLEST_VALUE = 1E-100; /** The logarithm base. */ private double base = 10.0; /** The logarithm of the base value - cached for performance. */ private double baseLog; /** The logarithms of the current axis range. */ private Range logRange; /** * The smallest value for the axis. In general, only positive values * can be plotted against a log axis but to simplify the generation of * bar charts (where the base of the bars is typically at 0.0) the axis * will return {@code smallestValue} as the translated value for 0.0. * It is important to make sure there are no real data values smaller * than this value. */ private double smallestValue; /** * The symbol used to represent the log base on the tick labels. If this * is {@code null} the numerical value will be displayed. */ private String baseSymbol; /** * The number formatter for the base value. */ private NumberFormat baseFormatter = new DecimalFormat("0"); /** * The tick selector (if not {@code null}, then auto-tick selection is * used). */ private TickSelector tickSelector = new NumberTickSelector(); /** * The tick size. If the tickSelector is not {@code null} then it is * used to auto-select an appropriate tick size and format. */ private double tickSize = 1.0; /** The tick formatter (never {@code null}). */ private Format tickLabelFormatter = new DecimalFormat("0.0"); /** * Creates a new log axis with a default base of 10. * * @param label the axis label ({@code null} permitted). */ public LogAxis3D(String label) { super(label, new Range(DEFAULT_SMALLEST_VALUE, 1.0)); this.base = 10.0; this.baseLog = Math.log(this.base); this.logRange = new Range(calculateLog(DEFAULT_SMALLEST_VALUE), calculateLog(1.0)); this.smallestValue = DEFAULT_SMALLEST_VALUE; } /** * Returns the logarithmic base value. The default value is {@code 10}. * * @return The logarithmic base value. */ public double getBase() { return this.base; } /** * Sets the logarithmic base value and sends an {@code Axis3DChangeEvent} * to all registered listeners. * * @param base the base value. */ public void setBase(double base) { this.base = base; this.baseLog = Math.log(base); fireChangeEvent(true); } /** * Returns the base symbol, used in tick labels for the axis. A typical * value would be "e" when using a natural logarithm scale. If this is * {@code null}, the tick labels will display the numerical base value. * The default value is {@code null}. * * @return The base symbol (possibly {@code null}). */ public String getBaseSymbol() { return this.baseSymbol; } /** * Sets the base symbol and sends an {@code Axis3DChangeEvent} to all * registered listeners. If you set this to {@code null}, the tick labels * will display a numerical representation of the base value. * * @param symbol the base symbol ({@code null} permitted). */ public void setBaseSymbol(String symbol) { this.baseSymbol = symbol; fireChangeEvent(false); } /** * Returns the formatter used for the log base value when it is displayed * in tick labels. The default value is {@code NumberFormat("0")}. * * @return The base formatter (never {@code null}). */ public NumberFormat getBaseFormatter() { return this.baseFormatter; } /** * Sets the formatter for the log base value and sends an * {@code Axis3DChangeEvent} to all registered listeners. * * @param formatter the formatter ({@code null} not permitted). */ public void setBaseFormatter(NumberFormat formatter) { Args.nullNotPermitted(formatter, "formatter"); this.baseFormatter = formatter; fireChangeEvent(false); } /** * Returns the smallest positive data value that will be represented on * the axis. This will be used as the lower bound for the axis if the * data range contains any value from {@code 0.0} up to this value. * * @return The smallest value. */ public double getSmallestValue() { return this.smallestValue; } /** * Sets the smallest positive data value that will be represented on the * axis and sends an {@code Axis3DChangeEvent} to all registered listeners. * * @param smallestValue the value (must be positive). */ public void setSmallestValue(double smallestValue) { Args.positiveRequired(smallestValue, "smallestValue"); this.smallestValue = smallestValue; fireChangeEvent(true); } /** * Returns the tick selector for the axis. * * @return The tick selector (possibly {@code null}). */ public TickSelector getTickSelector() { return this.tickSelector; } /** * Sets the tick selector and sends an {@code Axis3DChangeEvent} to all * registered listeners. * * @param selector the selector ({@code null} permitted). */ public void setTickSelector(TickSelector selector) { this.tickSelector = selector; fireChangeEvent(false); } /** * Returns the tick size to be used when the tick selector is * {@code null}. * * @return The tick size. */ public double getTickSize() { return this.tickSize; } /** * Sets the tick size and sends an {@code Axis3DChangeEvent} to all * registered listeners. * * @param tickSize the new tick size. */ public void setTickSize(double tickSize) { this.tickSize = tickSize; fireChangeEvent(false); } /** * Returns the tick label formatter. The default value is * {@code DecimalFormat("0.0")}. * * @return The tick label formatter (never {@code null}). */ public Format getTickLabelFormatter() { return this.tickLabelFormatter; } /** * Sets the formatter for the tick labels and sends an * {@code Axis3DChangeEvent} to all registered listeners. * * @param formatter the formatter ({@code null} not permitted). */ public void setTickLabelFormatter(Format formatter) { Args.nullNotPermitted(formatter, "formatter"); this.tickLabelFormatter = formatter; fireChangeEvent(false); } /** * Sets the range for the axis. This method is overridden to check that * the range does not contain negative values, and to update the log values * for the range. * * @param range the range ({@code nul} not permitted). */ @Override public void setRange(Range range) { Args.nullNotPermitted(range, "range"); this.range = new Range(Math.max(range.getMin(), this.smallestValue), range.getMax()); this.logRange = new Range(calculateLog(this.range.getMin()), calculateLog(this.range.getMax())); fireChangeEvent(true); } /** * Sets the range for the axis. This method is overridden to check that * the range does not contain negative values, and to update the log values * for the range. * * @param min the lower bound for the range. * @param max the upper bound for the range. */ @Override public void setRange(double min, double max) { Args.negativeNotPermitted(min, "min"); this.range = new Range(Math.max(min, this.smallestValue), max); this.logRange = new Range(calculateLog(this.range.getMin()), calculateLog(this.range.getMax())); fireChangeEvent(true); } @Override protected void updateRange(Range range) { this.range = range; this.logRange = new Range(calculateLog(this.range.getMin()), calculateLog(this.range.getMax())); } /** * Calculates the log of the given {@code value}, using the current base. * * @param value the value (negatives not permitted). * * @return The log of the given value. * * @see #calculateValue(double) * @see #getBase() */ public final double calculateLog(double value) { return Math.log(value) / this.baseLog; } /** * Calculates the value from a given log value. * * @param log the log value. * * @return The value with the given log. * * @see #calculateLog(double) * @see #getBase() */ public final double calculateValue(double log) { return Math.pow(this.base, log); } /** * Translates a data value to a world coordinate, assuming that the axis * begins at the origin and has the specified length. * * @param value the data value. * @param length the axis length in world coordinates. * * @return The world coordinate of this data value on the axis. */ @Override public double translateToWorld(double value, double length) { double logv = calculateLog(value); double percent = this.logRange.percent(logv); if (isInverted()) { percent = 1.0 - percent; } return percent * length; } /** * Draws the axis. * * @param g2 the graphics target ({@code null} not permitted). * @param startPt the starting point. * @param endPt the ending point. * @param opposingPt an opposing point (labels will be on the other side * of the line). * @param tickData the tick data (including anchor points calculated by * the 3D engine). * @param info an object to be populated with rendering info * ({@code null} permitted). * @param hinting perform element hinting? */ @Override public void draw(Graphics2D g2, Point2D startPt, Point2D endPt, Point2D opposingPt, List tickData, RenderingInfo info, boolean hinting) { if (!isVisible()) { return; } // draw a line for the axis g2.setStroke(getLineStroke()); g2.setPaint(getLineColor()); Line2D axisLine = new Line2D.Float(startPt, endPt); g2.draw(axisLine); // draw the tick marks and labels double tickMarkLength = getTickMarkLength(); double tickLabelOffset = getTickLabelOffset(); g2.setPaint(getTickMarkPaint()); g2.setStroke(getTickMarkStroke()); for (TickData t : tickData) { if (tickMarkLength > 0.0) { Line2D tickLine = Utils2D.createPerpendicularLine(axisLine, t.getAnchorPt(), tickMarkLength, opposingPt); g2.draw(tickLine); } } double maxTickLabelDim = 0.0; if (getTickLabelsVisible()) { g2.setFont(getTickLabelFont()); g2.setPaint(getTickLabelColor()); LabelOrientation orientation = getTickLabelOrientation(); if (orientation.equals(LabelOrientation.PERPENDICULAR)) { maxTickLabelDim = drawPerpendicularTickLabels(g2, axisLine, opposingPt, tickData, hinting); } else if (orientation.equals(LabelOrientation.PARALLEL)) { maxTickLabelDim = g2.getFontMetrics().getHeight(); double adj = g2.getFontMetrics().getAscent() / 2.0; drawParallelTickLabels(g2, axisLine, opposingPt, tickData, adj, hinting); } } // draw the axis label (if any)... if (getLabel() != null) { /* Shape labelBounds = */drawAxisLabel(getLabel(), g2, axisLine, opposingPt, maxTickLabelDim + tickMarkLength + tickLabelOffset + getLabelOffset(), info, hinting); } } private double drawPerpendicularTickLabels(Graphics2D g2, Line2D axisLine, Point2D opposingPt, List tickData, boolean hinting) { double result = 0.0; for (TickData t : tickData) { double theta = Utils2D.calculateTheta(axisLine); double thetaAdj = theta + Math.PI / 2.0; if (thetaAdj < -Math.PI / 2.0) { thetaAdj = thetaAdj + Math.PI; } if (thetaAdj > Math.PI / 2.0) { thetaAdj = thetaAdj - Math.PI; } Line2D perpLine = Utils2D.createPerpendicularLine(axisLine, t.getAnchorPt(), getTickMarkLength() + getTickLabelOffset(), opposingPt); double perpTheta = Utils2D.calculateTheta(perpLine); TextAnchor textAnchor = TextAnchor.CENTER_LEFT; if (Math.abs(perpTheta) > Math.PI / 2.0) { textAnchor = TextAnchor.CENTER_RIGHT; } double logy = calculateLog(t.getDataValue()); AttributedString as = createTickLabelAttributedString(logy, this.tickLabelFormatter); Rectangle2D nonRotatedBounds = new Rectangle2D.Double(); if (hinting) { Map m = new HashMap<>(); m.put("ref", "{\"type\": \"valueTickLabel\", \"axis\": " + axisStr() + ", \"value\": \"" + t.getDataValue() + "\"}"); g2.setRenderingHint(Chart3DHints.KEY_BEGIN_ELEMENT, m); } TextUtils.drawRotatedString(as, g2, (float) perpLine.getX2(), (float) perpLine.getY2(), textAnchor, thetaAdj, textAnchor, nonRotatedBounds); if (hinting) { g2.setRenderingHint(Chart3DHints.KEY_END_ELEMENT, true); } result = Math.max(result, nonRotatedBounds.getWidth()); } return result; } private void drawParallelTickLabels(Graphics2D g2, Line2D axisLine, Point2D opposingPt, List tickData, double adj, boolean hinting) { for (TickData t : tickData) { double theta = Utils2D.calculateTheta(axisLine); TextAnchor anchor = TextAnchor.CENTER; if (theta < -Math.PI / 2.0) { theta = theta + Math.PI; anchor = TextAnchor.CENTER; } if (theta > Math.PI / 2.0) { theta = theta - Math.PI; anchor = TextAnchor.CENTER; } Line2D perpLine = Utils2D.createPerpendicularLine(axisLine, t.getAnchorPt(), getTickMarkLength() + getTickLabelOffset() + adj, opposingPt); double logy = calculateLog(t.getDataValue()); AttributedString as = createTickLabelAttributedString(logy, this.tickSelector.getCurrentTickLabelFormat()); if (hinting) { Map m = new HashMap<>(); m.put("ref", "{\"type\": \"valueTickLabel\", \"axis\": " + axisStr() + ", \"value\": \"" + t.getDataValue() + "\"}"); g2.setRenderingHint(Chart3DHints.KEY_BEGIN_ELEMENT, m); } TextUtils.drawRotatedString(as, g2, (float) perpLine.getX2(), (float) perpLine.getY2(), anchor, theta, anchor, null); if (hinting) { g2.setRenderingHint(Chart3DHints.KEY_END_ELEMENT, true); } } } private AttributedString createTickLabelAttributedString(double logy, Format exponentFormatter) { String baseStr = this.baseSymbol; if (baseStr == null) { baseStr = this.baseFormatter.format(this.base); } String exponentStr = exponentFormatter.format(logy); AttributedString as = new AttributedString(baseStr + exponentStr); as.addAttributes(getTickLabelFont().getAttributes(), 0, (baseStr + exponentStr).length()); as.addAttribute(TextAttribute.SUPERSCRIPT, TextAttribute.SUPERSCRIPT_SUPER, baseStr.length(), baseStr.length() + exponentStr.length()); return as; } /** * Adjusts the range by adding the lower and upper margins on the * logarithmic range. * * @param range the range ({@code nul} not permitted). * * @return The adjusted range. */ @Override protected Range adjustedDataRange(Range range) { Args.nullNotPermitted(range, "range"); double logmin = calculateLog(Math.max(range.getMin(), this.smallestValue)); double logmax = calculateLog(range.getMax()); double length = logmax - logmin; double lm = length * getLowerMargin(); double um = length * getUpperMargin(); double lowerBound = calculateValue(logmin - lm); double upperBound = calculateValue(logmax + um); return new Range(lowerBound, upperBound); } /** * Selects a standard tick unit on the logarithmic range. * * @param g2 the graphics target ({@code null} not permitted). * @param pt0 the starting point. * @param pt1 the ending point. * @param opposingPt an opposing point. * * @return The tick unit (log increment). */ @Override public double selectTick(Graphics2D g2, Point2D pt0, Point2D pt1, Point2D opposingPt) { if (this.tickSelector == null) { return this.tickSize; } g2.setFont(getTickLabelFont()); FontMetrics fm = g2.getFontMetrics(); double length = pt0.distance(pt1); double rangeLength = this.logRange.getLength(); LabelOrientation orientation = getTickLabelOrientation(); if (orientation.equals(LabelOrientation.PERPENDICULAR)) { // based on the font height, we can determine roughly how many tick // labels will fit in the length available int height = fm.getHeight(); // the tickLabelFactor allows some control over how dense the labels // will be int maxTicks = (int) (length / (height * getTickLabelFactor())); if (maxTicks > 2 && this.tickSelector != null) { this.tickSelector.select(rangeLength / 2.0); // step through until we have too many ticks OR we run out of // tick sizes int tickCount = (int) (rangeLength / this.tickSelector.getCurrentTickSize()); while (tickCount < maxTicks) { this.tickSelector.previous(); tickCount = (int) (rangeLength / this.tickSelector.getCurrentTickSize()); } this.tickSelector.next(); this.tickSize = this.tickSelector.getCurrentTickSize(); this.tickLabelFormatter = this.tickSelector.getCurrentTickLabelFormat(); } else { this.tickSize = Double.NaN; } } else if (orientation.equals(LabelOrientation.PARALLEL)) { // choose a unit that is at least as large as the length of the axis this.tickSelector.select(rangeLength); boolean done = false; while (!done) { if (this.tickSelector.previous()) { // estimate the label widths, and do they overlap? AttributedString s0 = createTickLabelAttributedString( this.logRange.getMax() + this.logRange.getMin(), this.tickSelector.getCurrentTickLabelFormat()); TextLayout layout0 = new TextLayout(s0.getIterator(), g2.getFontRenderContext()); double w0 = layout0.getAdvance(); AttributedString s1 = createTickLabelAttributedString( this.logRange.getMax() + this.logRange.getMin(), this.tickSelector.getCurrentTickLabelFormat()); TextLayout layout1 = new TextLayout(s1.getIterator(), g2.getFontRenderContext()); double w1 = layout1.getAdvance(); double w = Math.max(w0, w1); int n = (int) (length / (w * this.getTickLabelFactor())); if (n < rangeLength / tickSelector.getCurrentTickSize()) { tickSelector.next(); done = true; } } else { done = true; } } this.tickSize = this.tickSelector.getCurrentTickSize(); this.tickLabelFormatter = this.tickSelector.getCurrentTickLabelFormat(); } return this.tickSize; } /** * Generates tick data for the axis, assuming the specified tick unit * (a log increment in this case). If the tick unit is Double.NaN then * ticks will be added for the bounds of the axis only. * * @param tickUnit the tick unit. * * @return A list of tick data items. */ @Override public List generateTickData(double tickUnit) { List result = new ArrayList<>(); if (Double.isNaN(tickUnit)) { result.add(new TickData(0, getRange().getMin())); result.add(new TickData(1, getRange().getMax())); } else { double logx = tickUnit * Math.ceil(this.logRange.getMin() / tickUnit); while (logx <= this.logRange.getMax()) { result.add(new TickData(this.logRange.percent(logx), calculateValue(logx))); logx += tickUnit; } } return result; } @Override public int hashCode() { int hash = 5; hash = 59 * hash + (int) (Double.doubleToLongBits(this.base) ^ (Double.doubleToLongBits(this.base) >>> 32)); hash = 59 * hash + (int) (Double.doubleToLongBits(this.smallestValue) ^ (Double.doubleToLongBits(this.smallestValue) >>> 32)); hash = 59 * hash + ObjectUtils.hashCode(this.baseSymbol); hash = 59 * hash + ObjectUtils.hashCode(this.baseFormatter); hash = 59 * hash + ObjectUtils.hashCode(this.tickSelector); hash = 59 * hash + (int) (Double.doubleToLongBits(this.tickSize) ^ (Double.doubleToLongBits(this.tickSize) >>> 32)); hash = 59 * hash + ObjectUtils.hashCode(this.tickLabelFormatter); return hash; } @Override public boolean equals(Object obj) { if (obj == null) { return false; } if (getClass() != obj.getClass()) { return false; } final LogAxis3D other = (LogAxis3D) obj; if (Double.doubleToLongBits(this.base) != Double.doubleToLongBits(other.base)) { return false; } if (Double.doubleToLongBits(this.smallestValue) != Double.doubleToLongBits(other.smallestValue)) { return false; } if (!ObjectUtils.equals(this.baseSymbol, other.baseSymbol)) { return false; } if (!ObjectUtils.equals(this.baseFormatter, other.baseFormatter)) { return false; } if (!ObjectUtils.equals(this.tickSelector, other.tickSelector)) { return false; } if (Double.doubleToLongBits(this.tickSize) != Double.doubleToLongBits(other.tickSize)) { return false; } if (!ObjectUtils.equals(this.tickLabelFormatter, other.tickLabelFormatter)) { return false; } return super.equals(obj); } } orson-charts-2.1.0/src/main/java/org/jfree/chart3d/axis/NumberAxis3D.java000066400000000000000000000616741417331271500260770ustar00rootroot00000000000000/* =========================================================== * Orson Charts : a 3D chart library for the Java(tm) platform * =========================================================== * * (C)opyright 2013-2022, by David Gilbert. All rights reserved. * * https://github.com/jfree/orson-charts * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . * * [Oracle and Java are registered trademarks of Oracle and/or its affiliates. * Other names may be trademarks of their respective owners.] * * If you do not wish to be bound by the terms of the GPL, an alternative * commercial license can be purchased. For details, please see visit the * Orson Charts home page: * * http://www.object-refinery.com/orsoncharts/index.html * */ package org.jfree.chart3d.axis; import java.awt.FontMetrics; import java.awt.Graphics2D; import java.awt.Shape; import java.awt.geom.Line2D; import java.awt.geom.Point2D; import java.awt.font.LineMetrics; import java.text.DecimalFormat; import java.text.Format; import java.io.Serializable; import java.util.ArrayList; import java.util.HashMap; import java.util.Map; import java.util.List; import org.jfree.chart3d.Chart3DHints; import org.jfree.chart3d.data.Range; import org.jfree.chart3d.graphics2d.TextAnchor; import org.jfree.chart3d.graphics3d.RenderedElement; import org.jfree.chart3d.graphics3d.RenderingInfo; import org.jfree.chart3d.graphics3d.internal.Utils2D; import org.jfree.chart3d.interaction.InteractiveElementType; import org.jfree.chart3d.internal.TextUtils; import org.jfree.chart3d.internal.Args; import org.jfree.chart3d.internal.ObjectUtils; import org.jfree.chart3d.plot.CategoryPlot3D; import org.jfree.chart3d.plot.XYZPlot; /** * A numerical axis for use with 3D plots (implements {@link ValueAxis3D}). * In a {@link CategoryPlot3D} the value axis (the vertical one) is numerical, * and in an {@link XYZPlot} all the axes (x, y and z) are numerical - for * all these cases an instance of this class can be used. *

* NOTE: This class is serializable, but the serialization format is subject * to change in future releases and should not be relied upon for persisting * instances of this class. */ public class NumberAxis3D extends AbstractValueAxis3D implements ValueAxis3D, Serializable { /** * Default formatter for axis number values. Can be overwritten. */ private static final Format DEFAULT_TICK_LABEL_FORMATTER = new DecimalFormat("0.00"); /** * A flag indicating whether or not the auto-range calculation should * include zero. */ private boolean autoRangeIncludesZero; /** * A flag that controls how zero is handled when it falls within the * margins. If {@code true}, the margin is truncated at zero, if * {@code false} the margin is not changed. */ private boolean autoRangeStickyZero; /** * The tick selector (if not {@code null}, then auto-tick selection is * used). */ private TickSelector tickSelector; /** * The tick size. If the tickSelector is not {@code null} then it is * used to auto-select an appropriate tick size and format. */ private double tickSize; /** The tick formatter (never {@code null}). */ private Format tickLabelFormatter; /** * Creates a new axis with the specified label and default attributes. * * @param label the axis label ({@code null} permitted). */ public NumberAxis3D(String label) { this(label, new Range(0.0, 1.0)); } /** * Creates a new axis with the specified label and range. * * @param label the axis label ({@code null} permitted). * @param range the range ({@code null} not permitted). */ public NumberAxis3D(String label, Range range) { super(label, range); this.autoRangeIncludesZero = false; this.autoRangeStickyZero = true; this.tickSelector = new NumberTickSelector(); this.tickSize = range.getLength() / 10.0; this.tickLabelFormatter = DEFAULT_TICK_LABEL_FORMATTER; } /** * Returns the flag that determines whether or not the auto range * mechanism should force zero to be included in the range. The default * value is {@code false}. * * @return A boolean. */ public boolean getAutoRangeIncludesZero() { return this.autoRangeIncludesZero; } /** * Sets the flag that controls whether or not the auto range mechanism * should force zero to be included in the axis range, and sends an * {@link Axis3DChangeEvent} to all registered listeners. * * @param include the new flag value. */ public void setAutoRangeIncludeZero(boolean include) { this.autoRangeIncludesZero = include; fireChangeEvent(true); } /** * Returns the flag that controls the behaviour of the auto range * mechanism when zero falls into the axis margins. The default value * is {@code true}. * * @return A boolean. * * @see #setAutoRangeStickyZero(boolean) */ public boolean getAutoRangeStickyZero() { return this.autoRangeStickyZero; } /** * Sets the flag that controls the behaviour of the auto range mechanism * when zero falls into the axis margins. If {@code true}, when * zero is in the axis margin the axis range is truncated at zero. If * {@code false}, there is no special treatment. * * @param sticky the new flag value. */ public void setAutoRangeStickyZero(boolean sticky) { this.autoRangeStickyZero = sticky; fireChangeEvent(true); } /** * Returns the tick selector, an object that is responsible for choosing * standard tick units for the axis. The default value is a default * instance of {@link NumberTickSelector}. * * @return The tick selector. * * @see #setTickSelector(TickSelector) */ public TickSelector getTickSelector() { return this.tickSelector; } /** * Sets the tick selector and sends an {@link Axis3DChangeEvent} to all * registered listeners. * * @param selector the selector ({@code null} permitted). * * @see #getTickSelector() */ public void setTickSelector(TickSelector selector) { this.tickSelector = selector; fireChangeEvent(false); } /** * Returns the tick size (to be used when the tick selector is * {@code null}). * * @return The tick size. */ public double getTickSize() { return this.tickSize; } /** * Sets the tick size and sends an {@link Axis3DChangeEvent} to all * registered listeners. * * @param tickSize the new tick size. */ public void setTickSize(double tickSize) { this.tickSize = tickSize; fireChangeEvent(false); } /** * Returns the tick label formatter. The default value is * {@code DecimalFormat("0.00")}. * * @return The tick label formatter (never {@code null}). */ public Format getTickLabelFormatter() { return this.tickLabelFormatter; } /** * Sets the formatter for the tick labels and sends an * {@link Axis3DChangeEvent} to all registered listeners. * * @param formatter the formatter ({@code null} not permitted). */ public void setTickLabelFormatter(Format formatter) { Args.nullNotPermitted(formatter, "formatter"); this.tickLabelFormatter = formatter; fireChangeEvent(false); } /** * Adjusts the range by adding the lower and upper margins and taking into * account also the {@code autoRangeStickyZero} flag. * * @param range the range ({@code null} not permitted). * * @return The adjusted range. */ @Override protected Range adjustedDataRange(Range range) { Args.nullNotPermitted(range, "range"); double lm = range.getLength() * getLowerMargin(); double um = range.getLength() * getUpperMargin(); double lowerBound = range.getMin() - lm; double upperBound = range.getMax() + um; if (this.autoRangeIncludesZero) { lowerBound = Math.min(lowerBound, 0.0); upperBound = Math.max(upperBound, 0.0); } // does zero fall in the margins? if (this.autoRangeStickyZero) { if (0.0 <= range.getMin() && 0.0 > lowerBound) { lowerBound = 0.0; } if (0.0 >= range.getMax() && 0.0 < upperBound) { upperBound = 0.0; } } if ((upperBound - lowerBound) < getMinAutoRangeLength()) { double adj = (getMinAutoRangeLength() - (upperBound - lowerBound)) / 2.0; lowerBound -= adj; upperBound += adj; } return new Range(lowerBound, upperBound); } /** * Draws the axis to the supplied graphics target ({@code g2}, with the * specified starting and ending points for the line. This method is used * internally, you should not need to call it directly. * * @param g2 the graphics target ({@code null} not permitted). * @param pt0 the starting point ({@code null} not permitted). * @param pt1 the ending point ({@code null} not permitted). * @param opposingPt an opposing point (to determine which side of the * axis line the labels should appear, {@code null} not permitted). * @param tickData tick details ({@code null} not permitted). * @param info an object to be populated with rendering info * ({@code null} permitted). * @param hinting perform element hinting? */ @Override public void draw(Graphics2D g2, Point2D pt0, Point2D pt1, Point2D opposingPt, List tickData, RenderingInfo info, boolean hinting) { if (!isVisible()) { return; } if (pt0.equals(pt1)) { return; } // draw a line for the axis g2.setStroke(getLineStroke()); g2.setPaint(getLineColor()); Line2D axisLine = new Line2D.Float(pt0, pt1); g2.draw(axisLine); // draw the tick marks and labels g2.setFont(getTickLabelFont()); // we track the max width or height of the labels to know how far to // offset the axis label when we draw it later double maxTickLabelDim = 0.0; if (getTickLabelOrientation().equals(LabelOrientation.PARALLEL)) { LineMetrics lm = g2.getFontMetrics().getLineMetrics("123", g2); maxTickLabelDim = lm.getHeight(); } double tickMarkLength = getTickMarkLength(); double tickLabelOffset = getTickLabelOffset(); g2.setPaint(getTickMarkPaint()); g2.setStroke(getTickMarkStroke()); for (TickData t : tickData) { if (tickMarkLength > 0.0) { Line2D tickLine = Utils2D.createPerpendicularLine(axisLine, t.getAnchorPt(), tickMarkLength, opposingPt); g2.draw(tickLine); } String tickLabel = this.tickLabelFormatter.format(t.getDataValue()); if (getTickLabelOrientation().equals( LabelOrientation.PERPENDICULAR)) { maxTickLabelDim = Math.max(maxTickLabelDim, g2.getFontMetrics().stringWidth(tickLabel)); } } if (getTickLabelsVisible()) { g2.setPaint(getTickLabelColor()); if (getTickLabelOrientation().equals( LabelOrientation.PERPENDICULAR)) { drawPerpendicularTickLabels(g2, axisLine, opposingPt, tickData, info, hinting); } else { drawParallelTickLabels(g2, axisLine, opposingPt, tickData, info, hinting); } } else { maxTickLabelDim = 0.0; } // draw the axis label (if any)... if (getLabel() != null) { Shape labelBounds = drawAxisLabel(getLabel(), g2, axisLine, opposingPt, maxTickLabelDim + tickMarkLength + tickLabelOffset + getLabelOffset(), info, hinting); } } /** * Draws tick labels parallel to the axis. * * @param g2 the graphics target ({@code null} not permitted). * @param axisLine the axis line ({@code null} not permitted). * @param opposingPt an opposing point (to determine on which side the * labels appear, {@code null} not permitted). * @param tickData the tick data ({@code null} not permitted). * @param info if not {@code null} this object will be updated with * {@link RenderedElement} instances for each of the tick labels. */ private void drawParallelTickLabels(Graphics2D g2, Line2D axisLine, Point2D opposingPt, List tickData, RenderingInfo info, boolean hinting) { g2.setFont(getTickLabelFont()); double halfAscent = g2.getFontMetrics().getAscent() / 2.0; for (TickData t : tickData) { Line2D perpLine = Utils2D.createPerpendicularLine(axisLine, t.getAnchorPt(), getTickMarkLength() + getTickLabelOffset() + halfAscent, opposingPt); double axisTheta = Utils2D.calculateTheta(axisLine); TextAnchor textAnchor = TextAnchor.CENTER; if (axisTheta >= Math.PI / 2.0) { axisTheta = axisTheta - Math.PI; } else if (axisTheta <= -Math.PI / 2) { axisTheta = axisTheta + Math.PI; } String tickLabel = this.tickLabelFormatter.format( t.getDataValue()); if (hinting) { Map m = new HashMap<>(); m.put("ref", "{\"type\": \"valueTickLabel\", \"axis\": \"" + axisStr() + "\", \"value\": \"" + t.getDataValue() + "\"}"); g2.setRenderingHint(Chart3DHints.KEY_BEGIN_ELEMENT, m); } Shape bounds = TextUtils.drawRotatedString(tickLabel, g2, (float) perpLine.getX2(), (float) perpLine.getY2(), textAnchor, axisTheta, textAnchor); if (hinting) { g2.setRenderingHint(Chart3DHints.KEY_END_ELEMENT, true); } if (info != null) { RenderedElement tickLabelElement = new RenderedElement( InteractiveElementType.VALUE_AXIS_TICK_LABEL, bounds); tickLabelElement.setProperty("axis", axisStr()); tickLabelElement.setProperty("value", t.getDataValue()); info.addOffsetElement(tickLabelElement); } } } /** * Draws tick labels perpendicular to the axis. * * @param g2 the graphics target ({@code null} not permitted). * @param axisLine the axis line ({@code null} not permitted). * @param opposingPt an opposing point (to determine on which side the * labels appear, {@code null} not permitted). * @param tickData the tick data ({@code null} not permitted). * @param info if not {@code null} this object will be updated with * {@link RenderedElement} instances for each of the tick labels. */ private void drawPerpendicularTickLabels(Graphics2D g2, Line2D axisLine, Point2D opposingPt, List tickData, RenderingInfo info, boolean hinting) { for (TickData t : tickData) { double theta = Utils2D.calculateTheta(axisLine); double thetaAdj = theta + Math.PI / 2.0; if (thetaAdj < -Math.PI / 2.0) { thetaAdj = thetaAdj + Math.PI; } if (thetaAdj > Math.PI / 2.0) { thetaAdj = thetaAdj - Math.PI; } Line2D perpLine = Utils2D.createPerpendicularLine(axisLine, t.getAnchorPt(), getTickMarkLength() + getTickLabelOffset(), opposingPt); double perpTheta = Utils2D.calculateTheta(perpLine); TextAnchor textAnchor = TextAnchor.CENTER_LEFT; if (Math.abs(perpTheta) > Math.PI / 2.0) { textAnchor = TextAnchor.CENTER_RIGHT; } String tickLabel = this.tickLabelFormatter.format( t.getDataValue()); if (hinting) { Map m = new HashMap<>(); m.put("ref", "{\"type\": \"valueTickLabel\", \"axis\": \"" + axisStr() + "\", \"value\": \"" + t.getDataValue() + "\"}"); g2.setRenderingHint(Chart3DHints.KEY_BEGIN_ELEMENT, m); } Shape bounds = TextUtils.drawRotatedString(tickLabel, g2, (float) perpLine.getX2(), (float) perpLine.getY2(), textAnchor, thetaAdj, textAnchor); if (hinting) { g2.setRenderingHint(Chart3DHints.KEY_END_ELEMENT, true); } if (info != null) { RenderedElement tickLabelElement = new RenderedElement( InteractiveElementType.VALUE_AXIS_TICK_LABEL, bounds); tickLabelElement.setProperty("axis", axisStr()); tickLabelElement.setProperty("value", t.getDataValue()); info.addOffsetElement(tickLabelElement); } } } /** * Converts a data value to world coordinates, taking into account the * current axis range (assumes the world axis is zero-based and has the * specified length). * * @param value the data value (in axis units). * @param length the length of the (zero based) world axis. * * @return A world coordinate. */ @Override public double translateToWorld(double value, double length) { double p = getRange().percent(value, isInverted()); return length * p; } /** * Selects a tick size that is appropriate for drawing the axis from * {@code pt0} to {@code pt1}. * * @param g2 the graphics target ({@code null} not permitted). * @param pt0 the starting point for the axis. * @param pt1 the ending point for the axis. * @param opposingPt a point on the opposite side of the line from where * the labels should be drawn. */ @Override public double selectTick(Graphics2D g2, Point2D pt0, Point2D pt1, Point2D opposingPt) { if (this.tickSelector == null) { return this.tickSize; } g2.setFont(getTickLabelFont()); FontMetrics fm = g2.getFontMetrics(getTickLabelFont()); double length = pt0.distance(pt1); LabelOrientation orientation = getTickLabelOrientation(); if (orientation.equals(LabelOrientation.PERPENDICULAR)) { // based on the font height, we can determine roughly how many tick // labels will fit in the length available double height = fm.getHeight(); // the tickLabelFactor allows some control over how dense the labels // will be int maxTicks = (int) (length / (height * getTickLabelFactor())); if (maxTicks > 2 && this.tickSelector != null) { double rangeLength = getRange().getLength(); this.tickSelector.select(rangeLength / 2.0); // step through until we have too many ticks OR we run out of // tick sizes int tickCount = (int) (rangeLength / this.tickSelector.getCurrentTickSize()); while (tickCount < maxTicks) { this.tickSelector.previous(); tickCount = (int) (rangeLength / this.tickSelector.getCurrentTickSize()); } this.tickSelector.next(); this.tickSize = this.tickSelector.getCurrentTickSize(); // TFE, 20180911: don't overwrite any formatter explicitly set if (DEFAULT_TICK_LABEL_FORMATTER.equals(this.tickLabelFormatter)) { this.tickLabelFormatter = this.tickSelector.getCurrentTickLabelFormat(); } } else { this.tickSize = Double.NaN; } } else if (orientation.equals(LabelOrientation.PARALLEL)) { // choose a unit that is at least as large as the length of the axis this.tickSelector.select(getRange().getLength()); boolean done = false; while (!done) { if (this.tickSelector.previous()) { // estimate the label widths, and do they overlap? Format f = this.tickSelector.getCurrentTickLabelFormat(); String s0 = f.format(this.range.getMin()); String s1 = f.format(this.range.getMax()); double w0 = fm.stringWidth(s0); double w1 = fm.stringWidth(s1); double w = Math.max(w0, w1); int n = (int) (length / (w * this.getTickLabelFactor())); if (n < getRange().getLength() / tickSelector.getCurrentTickSize()) { tickSelector.next(); done = true; } } else { done = true; } } this.tickSize = this.tickSelector.getCurrentTickSize(); // TFE, 20180911: don't overwrite any formatter explicitly set if (DEFAULT_TICK_LABEL_FORMATTER.equals(this.tickLabelFormatter)) { this.tickLabelFormatter = this.tickSelector.getCurrentTickLabelFormat(); } } return this.tickSize; } /** * Generates a list of tick data items for the specified tick unit. This * data will be passed to the 3D engine and will be updated with a 2D * projection that can later be used to write the axis tick labels in the * appropriate places. *

* If {@code tickUnit} is {@code Double.NaN}, then tick data is * generated for just the bounds of the axis. * * @param tickUnit the tick unit. * * @return A list of tick data (never {@code null}). */ @Override public List generateTickData(double tickUnit) { List result = new ArrayList<>(); if (Double.isNaN(tickUnit)) { result.add(new TickData(0, getRange().getMin())); result.add(new TickData(1, getRange().getMax())); } else { double x = tickUnit * Math.ceil(this.range.getMin() / tickUnit); while (x <= this.range.getMax()) { result.add(new TickData(this.range.percent(x, isInverted()), x)); x += tickUnit; } } return result; } /** * Tests this instance for equality with an arbitrary object. * * @param obj the object to test against ({@code null} permitted). * * @return A boolean. */ @Override public boolean equals(Object obj) { if (obj == this) { return true; } if (!(obj instanceof NumberAxis3D)) { return false; } NumberAxis3D that = (NumberAxis3D) obj; if (this.autoRangeIncludesZero != that.autoRangeIncludesZero) { return false; } if (this.autoRangeStickyZero != that.autoRangeStickyZero) { return false; } if (this.tickSize != that.tickSize) { return false; } if (!ObjectUtils.equals(this.tickSelector, that.tickSelector)) { return false; } if (!this.tickLabelFormatter.equals(that.tickLabelFormatter)) { return false; } return super.equals(obj); } /** * Returns a hash code for this instance. * * @return A hash code. */ @Override public int hashCode() { int hash = 3; hash = 59 * hash + (int) (Double.doubleToLongBits(this.tickSize) ^ (Double.doubleToLongBits(this.tickSize) >>> 32)); hash = 59 * hash + ObjectUtils.hashCode(this.tickLabelFormatter); return hash; } } orson-charts-2.1.0/src/main/java/org/jfree/chart3d/axis/NumberTickSelector.java000066400000000000000000000160221417331271500273620ustar00rootroot00000000000000/* =========================================================== * Orson Charts : a 3D chart library for the Java(tm) platform * =========================================================== * * (C)opyright 2013-2022, by David Gilbert. All rights reserved. * * https://github.com/jfree/orson-charts * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . * * [Oracle and Java are registered trademarks of Oracle and/or its affiliates. * Other names may be trademarks of their respective owners.] * * If you do not wish to be bound by the terms of the GPL, an alternative * commercial license can be purchased. For details, please see visit the * Orson Charts home page: * * http://www.object-refinery.com/orsoncharts/index.html * */ package org.jfree.chart3d.axis; import java.io.Serializable; import java.text.DecimalFormat; import java.text.Format; import org.jfree.chart3d.internal.Args; /** * A {@link TickSelector} implementation that selects tick units in multiples * of 1, 2 and 5. *

* NOTE: This class is serializable, but the serialization format is subject * to change in future releases and should not be relied upon for persisting * instances of this class. */ @SuppressWarnings("serial") public class NumberTickSelector implements TickSelector, Serializable { private int power = 0; private int factor = 1; /** * A flag to track if the units are percentage values, in which case the * formatter should display less decimal places. */ private boolean percentage; /** * Creates a new instance. */ public NumberTickSelector() { this(false); } /** * Creates a new instance, with the option to display the tick values as * percentages. The axis follows the normal convention that values in the * range 0.0 to 1.0 a represented as 0% to 100%. * * @param percentage format the tick values as percentages. */ public NumberTickSelector(boolean percentage) { this.power = 0; this.factor = 1; this.percentage = percentage; } /** * Selects and returns a standard tick size that is greater than or equal to * the specified reference value and, ideally, as close to it as possible * (to minimise the number of iterations used by axes to determine the tick * size to use). After a call to this method, the * {@link #getCurrentTickSize()} method should return the selected tick * size (there is a "pointer" to this tick size), the {@link #next()} * method should move the pointer to the next (larger) standard tick size, * and the {@link #previous()} method should move the pointer to the * previous (smaller) standard tick size. * * @param reference the reference value (must be positive and finite). * * @return The selected tick size. */ @Override public double select(double reference) { Args.finitePositiveRequired(reference, "reference"); this.power = (int) Math.ceil(Math.log10(reference)); this.factor = 1; return getCurrentTickSize(); } /** * Move the cursor to the next (larger) tick size, if there is one. * Returns {@code true} in the case that the cursor is moved, and * {@code false} where there are a finite number of tick sizes and the * current tick size is the largest available. */ @Override public boolean next() { if (factor == 1) { factor = 2; return true; } if (factor == 2) { factor = 5; return true; } if (factor == 5) { power++; factor = 1; return true; } throw new IllegalStateException("We should never get here."); } /** * Move the cursor to the previous (smaller) tick size, if there is one. * Returns {@code true} in the case that the cursor is moved, and * {@code false} where there are a finite number of tick sizes and the * current tick size is the smallest available. */ @Override public boolean previous() { if (factor == 1) { factor = 5; power--; return true; } if (factor == 2) { factor = 1; return true; } if (factor == 5) { factor = 2; return true; } throw new IllegalStateException("We should never get here."); } @Override public double getCurrentTickSize() { return this.factor * Math.pow(10.0, this.power); } private final DecimalFormat dfNeg4 = new DecimalFormat("0.0000"); private final DecimalFormat dfNeg3 = new DecimalFormat("0.000"); private final DecimalFormat dfNeg2 = new DecimalFormat("0.00"); private final DecimalFormat dfNeg1 = new DecimalFormat("0.0"); private final DecimalFormat df0 = new DecimalFormat("#,##0"); private final DecimalFormat dfNeg4P = new DecimalFormat("0.00%"); private final DecimalFormat dfNeg3P = new DecimalFormat("0.0%"); private final DecimalFormat dfNeg2P = new DecimalFormat("0%"); private final DecimalFormat dfNeg1P = new DecimalFormat("0%"); private final DecimalFormat df0P = new DecimalFormat("#,##0%"); @Override public Format getCurrentTickLabelFormat() { if (power == -4) { return this.percentage ? dfNeg4P : dfNeg4; } if (power == -3) { return this.percentage ? dfNeg3P : dfNeg3; } if (power == -2) { return this.percentage ? dfNeg2P : dfNeg2; } if (power == -1) { return this.percentage ? dfNeg1P : dfNeg1; } if (power >= 0 && power <= 6) { return this.percentage ? df0P : df0; } return this.percentage ? new DecimalFormat("0.0000E0%") : new DecimalFormat("0.0000E0"); } /** * Tests this instance for equality with an arbitrary object. * * @param obj the object ({@code null} permitted). * * @return A boolean. */ @Override public boolean equals(Object obj) { if (obj == this) { return true; } if (!(obj instanceof NumberTickSelector)) { return false; } NumberTickSelector that = (NumberTickSelector) obj; if (this.percentage != that.percentage) { return false; } return true; } } orson-charts-2.1.0/src/main/java/org/jfree/chart3d/axis/StandardCategoryAxis3D.java000066400000000000000000001145011417331271500300710ustar00rootroot00000000000000/* =========================================================== * Orson Charts : a 3D chart library for the Java(tm) platform * =========================================================== * * (C)opyright 2013-2022, by David Gilbert. All rights reserved. * * https://github.com/jfree/orson-charts * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . * * [Oracle and Java are registered trademarks of Oracle and/or its affiliates. * Other names may be trademarks of their respective owners.] * * If you do not wish to be bound by the terms of the GPL, an alternative * commercial license can be purchased. For details, please see visit the * Orson Charts home page: * * http://www.object-refinery.com/orsoncharts/index.html * */ package org.jfree.chart3d.axis; import java.awt.BasicStroke; import java.awt.Color; import java.awt.Graphics2D; import java.awt.Paint; import java.awt.Shape; import java.awt.Stroke; import java.awt.font.LineMetrics; import java.awt.geom.Line2D; import java.awt.geom.Point2D; import java.io.IOException; import java.io.ObjectInputStream; import java.io.ObjectOutputStream; import java.io.Serializable; import java.util.ArrayList; import java.util.LinkedHashMap; import java.util.List; import java.util.HashMap; import java.util.Map; import org.jfree.chart3d.graphics3d.internal.Utils2D; import org.jfree.chart3d.Chart3DHints; import org.jfree.chart3d.ChartElementVisitor; import org.jfree.chart3d.data.Range; import org.jfree.chart3d.data.category.CategoryDataset3D; import org.jfree.chart3d.graphics2d.TextAnchor; import org.jfree.chart3d.graphics3d.RenderedElement; import org.jfree.chart3d.graphics3d.RenderingInfo; import org.jfree.chart3d.interaction.InteractiveElementType; import org.jfree.chart3d.internal.Args; import org.jfree.chart3d.internal.ObjectUtils; import org.jfree.chart3d.internal.SerialUtils; import org.jfree.chart3d.internal.TextUtils; import org.jfree.chart3d.label.CategoryLabelGenerator; import org.jfree.chart3d.label.StandardCategoryLabelGenerator; import org.jfree.chart3d.marker.CategoryMarker; import org.jfree.chart3d.marker.CategoryMarkerType; import org.jfree.chart3d.marker.Marker; import org.jfree.chart3d.marker.MarkerData; import org.jfree.chart3d.plot.CategoryPlot3D; import org.jfree.chart3d.renderer.category.AreaRenderer3D; /** * An axis that displays categories. *

* NOTE: This class is serializable, but the serialization format is subject * to change in future releases and should not be relied upon for persisting * instances of this class. */ @SuppressWarnings("serial") public class StandardCategoryAxis3D extends AbstractAxis3D implements CategoryAxis3D, Serializable { /** The categories. */ private List> categories; /** * The axis range (never {@code null}). */ private Range range; private boolean inverted; /** The percentage margin to leave at the lower end of the axis. */ private double lowerMargin; /** The percentage margin to leave at the upper end of the axis. */ private double upperMargin; /** * Hide half of the first category? This brings the category label * closer to the beginning of the axis. It is useful if the renderer * doesn't make full use of the category space for the first item. */ private boolean firstCategoryHalfWidth = false; /** * Hide half of the last category? This brings the category label * closer to the end of the axis. It is useful if the renderer * doesn't make full use of the category space for the last item. */ private boolean lastCategoryHalfWidth = false; /** * The tick mark length (in Java2D units). When this is 0.0, no tick * marks will be drawn. */ private double tickMarkLength; /** The tick mark stroke (never {@code null}). */ private transient Stroke tickMarkStroke; /** The tick mark paint (never {@code null}). */ private transient Paint tickMarkPaint; /** The tick label generator. */ private CategoryLabelGenerator tickLabelGenerator; /** * The tick label offset (in Java2D units). This is the gap between the * tick marks and their associated labels. */ private double tickLabelOffset; /** The orientation for the tick labels. */ private LabelOrientation tickLabelOrientation; /** * The maximum number of offset levels to use for tick labels on the axis. */ private int maxTickLabelLevels = 3; /** * The tick label factor (used as a multiplier for the tick label width * when checking for overlapping labels). */ private double tickLabelFactor = 1.2; /** * The markers for the axis (this may be empty, but not {@code null}). */ private Map markers; /** A flag to indicate that this axis has been configured as a row axis. */ private boolean isRowAxis; /** * A flag to indicate that this axis has been configured as a column * axis. */ private boolean isColumnAxis; /** * Default constructor. */ public StandardCategoryAxis3D() { this(null); } /** * Creates a new axis with the specified label. * * @param label the axis label ({@code null} permitted). */ public StandardCategoryAxis3D(String label) { super(label); this.categories = new ArrayList<>(); this.range = new Range(0.0, 1.0); this.lowerMargin = 0.05; this.upperMargin = 0.05; this.firstCategoryHalfWidth = false; this.lastCategoryHalfWidth = false; this.tickMarkLength = 3.0; this.tickMarkPaint = Color.GRAY; this.tickMarkStroke = new BasicStroke(0.5f); this.tickLabelGenerator = new StandardCategoryLabelGenerator(); this.tickLabelOffset = 5.0; this.tickLabelOrientation = LabelOrientation.PARALLEL; this.tickLabelFactor = 1.4; this.maxTickLabelLevels = 3; this.markers = new LinkedHashMap<>(); this.isRowAxis = false; this.isColumnAxis = false; } /** * Returns {@code true} if this axis has been configured as a * row axis for the plot that it belongs to, and {@code false} * otherwise. * * @return A boolean. * * @since 1.3 */ @Override public boolean isRowAxis() { return isRowAxis; } /** * Returns {@code true} if this axis has been configured as a * column axis for the plot that it belongs to, and {@code false} * otherwise. * * @return A boolean. * * @since 1.3 */ @Override public boolean isColumnAxis() { return isColumnAxis; } /** * Returns the range for the axis. By convention, the category axes have * a range from 0.0 to 1.0. * * @return The range. */ @Override public Range getRange() { return this.range; } /** * Sets the range for the axis and sends an {@link Axis3DChangeEvent} to * all registered listeners. * * @param lowerBound the lower bound. * @param upperBound the upper bound. */ @Override public void setRange(double lowerBound, double upperBound) { setRange(new Range(lowerBound, upperBound)); } /** * Sets the range for the axis and sends an {@link Axis3DChangeEvent} to * all registered listeners. Note that changing the range for the * category axis will have no visible effect. * * @param range the range ({@code null} not permitted). */ @Override public void setRange(Range range) { Args.nullNotPermitted(range, "range"); this.range = range; fireChangeEvent(true); } /** * Returns the margin to leave at the lower end of the axis, as a * percentage of the axis length. The default is {@code 0.05} (five * percent). * * @return The lower margin. */ public double getLowerMargin() { return this.lowerMargin; } /** * Sets the margin to leave at the lower end of the axis and sends an * {@link Axis3DChangeEvent} to all registered listeners. * * @param margin the margin. */ public void setLowerMargin(double margin) { this.lowerMargin = margin; fireChangeEvent(true); } /** * Returns the margin to leave at the upper end of the axis, as a * percentage of the axis length. The default is {@code 0.05} (five * percent). * * @return The lower margin. */ public double getUpperMargin() { return this.upperMargin; } /** * Sets the margin to leave at the upper end of the axis and sends an * {@link Axis3DChangeEvent} to all registered listeners. * * @param margin the margin. */ public void setUpperMargin(double margin) { this.upperMargin = margin; fireChangeEvent(true); } /** * Returns {@code true} if the first category on the axis should * occupy half the normal width, and {@code false} otherwise. * * @return A boolean. * * @see #setFirstCategoryHalfWidth(boolean) */ public boolean isFirstCategoryHalfWidth() { return this.firstCategoryHalfWidth; } /** * Sets the flag that controls whether the first category on the axis * occupies a full or half width, and sends an {@link Axis3DChangeEvent} * to all registered listeners. There are some renderers where the * charts look better when half-widths are used (for example, * {@link AreaRenderer3D}). * * @param half half width? * * @see #setLastCategoryHalfWidth(boolean) */ public void setFirstCategoryHalfWidth(boolean half) { this.firstCategoryHalfWidth = half; fireChangeEvent(true); } /** * Returns {@code true} if the last category on the axis should * occupy half the normal width, and {@code false} otherwise. * * @return A boolean. * * @see #setLastCategoryHalfWidth(boolean) */ public boolean isLastCategoryHalfWidth() { return this.lastCategoryHalfWidth; } /** * Sets the flag that controls whether the last category on the axis * occupies a full or half width, and sends an {@link Axis3DChangeEvent} * to all registered listeners. There are some renderers where the * charts look better when half-widths are used (for example, * {@link AreaRenderer3D}). * * @param half half width? * * @see #setFirstCategoryHalfWidth(boolean) */ public void setLastCategoryHalfWidth(boolean half) { this.lastCategoryHalfWidth = half; fireChangeEvent(true); } /** * Returns the tick mark length (in Java2D units). The default value * is {@code 3.0}. * * @return The tick mark length. */ public double getTickMarkLength() { return this.tickMarkLength; } /** * Sets the tick mark length (in Java2D units) and sends an * {@link Axis3DChangeEvent} to all registered listeners. You can set * the length to {@code 0.0} if you don't want any tick marks on the * axis. * * @param length the length (in Java2D units). */ public void setTickMarkLength(double length) { this.tickMarkLength = length; fireChangeEvent(false); } /** * Returns the paint used to draw the tick marks, if they are visible. * The default value is {@code Color.GRAY}. * * @return The paint used to draw the tick marks (never {@code null}). */ public Paint getTickMarkPaint() { return this.tickMarkPaint; } /** * Sets the paint used to draw the tick marks and sends an * {@link Axis3DChangeEvent} to all registered listeners. * * @param paint the paint ({@code null} not permitted). */ public void setTickMarkPaint(Paint paint) { Args.nullNotPermitted(paint, "paint"); this.tickMarkPaint = paint; fireChangeEvent(false); } /** * Returns the stroke used to draw the tick marks, if they are visible. * The default value is {@code new BasicStroke(0.5f)}. * * @return The stroke used to draw the tick marks (never {@code null}). */ public Stroke getTickMarkStroke() { return this.tickMarkStroke; } /** * Sets the stroke used to draw the tick marks and sends an * {@link Axis3DChangeEvent} to all registered listeners. * * @param stroke the stroke ({@code null} not permitted). */ public void setTickMarkStroke(Stroke stroke) { Args.nullNotPermitted(stroke, "stroke"); this.tickMarkStroke = stroke; fireChangeEvent(false); } /** * Returns the tick label generator for the axis. This is an object that * is responsible for creating the category labels on the axis. You can * plug in your own instance to take full control over the generation * of category labels. * * @return The tick label generator for the axis (never {@code null}). * * @since 1.2 */ public CategoryLabelGenerator getTickLabelGenerator() { return this.tickLabelGenerator; } /** * Sets the tick label generator for the axis and sends a change event to * all registered listeners. * * @param generator the generator ({@code null} not permitted). * * @since 1.2 */ public void setTickLabelGenerator(CategoryLabelGenerator generator) { Args.nullNotPermitted(generator, "generator"); this.tickLabelGenerator = generator; fireChangeEvent(false); } /** * Returns the offset between the tick marks and the tick labels. The * default value is {@code 5.0}. * * @return The offset between the tick marks and the tick labels (in Java2D * units). */ public double getTickLabelOffset() { return this.tickLabelOffset; } /** * Sets the offset between the tick marks and the tick labels and sends * a {@link Axis3DChangeEvent} to all registered listeners. * * @param offset the offset. */ public void setTickLabelOffset(double offset) { this.tickLabelOffset = offset; fireChangeEvent(false); } /** * Returns the orientation for the tick labels. The default value is * {@link LabelOrientation#PARALLEL}. * * @return The orientation for the tick labels (never {@code null}). * * @since 1.2 */ public LabelOrientation getTickLabelOrientation() { return this.tickLabelOrientation; } /** * Sets the orientation for the tick labels and sends a change event to * all registered listeners. * * @param orientation the orientation ({@code null} not permitted). * * @since 1.2 */ public void setTickLabelOrientation(LabelOrientation orientation) { Args.nullNotPermitted(orientation, "orientation"); this.tickLabelOrientation = orientation; fireChangeEvent(false); } /** * Returns the maximum number of offset levels for the category labels on * the axis. The default value is 3. * * @return The maximum number of offset levels. * * @since 1.2 */ public int getMaxTickLabelLevels() { return this.maxTickLabelLevels; } /** * Sets the maximum number of offset levels for the category labels on the * axis and sends a change event to all registered listeners. * * @param levels the maximum number of levels. * * @since 1.2 */ public void setMaxTickLabelLevels(int levels) { this.maxTickLabelLevels = levels; fireChangeEvent(false); } /** * Returns the tick label factor. The default value is {@code 1.4}. * * @return The tick label factor. * * @since 1.2 */ public double getTickLabelFactor() { return this.tickLabelFactor; } /** * Sets the tick label factor and sends a change event to all registered * listeners. * * @param factor the new factor (should be at least 1.0). * * @since 1.2 */ public void setTickLabelFactor(double factor) { this.tickLabelFactor = factor; fireChangeEvent(false); } /** * Returns the marker with the specified key, if there is one. * * @param key the key ({@code null} not permitted). * * @return The marker (possibly {@code null}). * * @since 1.2 */ @Override public CategoryMarker getMarker(String key) { return this.markers.get(key); } /** * Sets the marker for the specified key and sends a change event to * all registered listeners. If there is an existing marker it is replaced * (and the axis will no longer listen for change events on the previous * marker). * * @param key the key that identifies the marker ({@code null} not * permitted). * @param marker the marker ({@code null} permitted). * * @since 1.2 */ public void setMarker(String key, CategoryMarker marker) { CategoryMarker existing = this.markers.get(key); if (existing != null) { existing.removeChangeListener(this); } this.markers.put(key, marker); if (marker != null) { marker.addChangeListener(this); } fireChangeEvent(false); } /** * Returns a new map containing the markers that are assigned to this axis. * * @return A map. * * @since 1.2 */ public Map getMarkers() { return new LinkedHashMap<>(this.markers); } /** * Returns the width of a single category in the units of the axis * range. * * @return The width of a single category. */ @Override public double getCategoryWidth() { double length = this.range.getLength(); double start = this.range.getMin() + (this.lowerMargin * length); double end = this.range.getMax() - (this.upperMargin * length); double available = (end - start); return available / this.categories.size(); } /** * Configures the axis to be used as a row axis for the specified * plot. This method is for internal use, you should not call it directly. * * @param plot the plot ({@code null} not permitted). */ @Override @SuppressWarnings("unchecked") public void configureAsRowAxis(CategoryPlot3D plot) { Args.nullNotPermitted(plot, "plot"); this.categories = plot.getDataset().getRowKeys(); this.isColumnAxis = false; this.isRowAxis = true; } /** * Configures the axis to be used as a column axis for the specified * plot. This method is for internal use, you won't normally need to call * it directly. * * @param plot the plot ({@code null} not permitted). */ @Override @SuppressWarnings("unchecked") public void configureAsColumnAxis(CategoryPlot3D plot) { Args.nullNotPermitted(plot, "plot"); this.categories = plot.getDataset().getColumnKeys(); this.isColumnAxis = true; this.isRowAxis = false; } /** * Returns the value for the specified category, or {@code Double.NaN} * if the category is not registered on the axis. * * @param category the category ({@code null} not permitted). * * @return The value. */ @Override public double getCategoryValue(Comparable category) { int index = this.categories.indexOf(category); if (index < 0) { return Double.NaN; } double length = this.range.getLength(); double start = this.range.getMin() + (this.lowerMargin * length); double end = this.range.getMax() - (this.upperMargin * length); double available = (end - start); double categoryCount = this.categories.size(); if (categoryCount == 1) { return (start + end) / 2.0; } if (this.firstCategoryHalfWidth) { categoryCount -= 0.5; } if (this.lastCategoryHalfWidth) { categoryCount -= 0.5; } double categoryWidth = 0.0; if (categoryCount > 0.0) { categoryWidth = available / categoryCount; } double adj = this.firstCategoryHalfWidth ? 0.0 : 0.5; return start + (adj + index) * categoryWidth; } /** * Translates a value on the axis to the equivalent coordinate in the * 3D world used to construct a model of the chart. * * @param value the value along the axis. * @param length the length of one side of the 3D box containing the model. * * @return A coordinate in 3D space. */ @Override public double translateToWorld(double value, double length) { double p = getRange().percent(value, isInverted()); return length * p; } /** * Draws the axis between the two points {@code pt0} and {@code pt1} in * Java2D space. * * @param g2 the graphics target ({@code null} not permitted). * @param pt0 the starting point for the axis ({@code null} not * permitted). * @param pt1 the ending point for the axis ({@code null} not * permitted). * @param opposingPt a point on the opposite side of the line from the * labels ({@code null} not permitted). * @param tickData the tick data, contains positioning anchors calculated * by the 3D engine ({@code null} not permitted). * @param info an object to be populated with rendering info * ({@code null} permitted). * @param hinting perform element hinting? */ @Override public void draw(Graphics2D g2, Point2D pt0, Point2D pt1, Point2D opposingPt, List tickData, RenderingInfo info, boolean hinting) { if (!isVisible()) { return; } if (pt0.equals(pt1)) { // if the axis starts and ends on the same point return; // there is nothing we can draw } // draw the axis line (if you want no line, setting the line color // to fully transparent will achieve this) g2.setStroke(getLineStroke()); g2.setPaint(getLineColor()); Line2D axisLine = new Line2D.Float(pt0, pt1); g2.draw(axisLine); // draw the tick marks - during this pass we will also find the maximum // tick label width g2.setPaint(this.tickMarkPaint); g2.setStroke(this.tickMarkStroke); g2.setFont(getTickLabelFont()); double maxTickLabelWidth = 0.0; for (TickData t : tickData) { if (this.tickMarkLength > 0.0) { Line2D tickLine = Utils2D.createPerpendicularLine(axisLine, t.getAnchorPt(), this.tickMarkLength, opposingPt); g2.draw(tickLine); } String tickLabel = t.getKeyLabel(); maxTickLabelWidth = Math.max(maxTickLabelWidth, g2.getFontMetrics().stringWidth(tickLabel)); } double maxTickLabelDim = maxTickLabelWidth; if (getTickLabelsVisible()) { g2.setPaint(getTickLabelColor()); if (this.tickLabelOrientation.equals( LabelOrientation.PERPENDICULAR)) { drawPerpendicularTickLabels(g2, axisLine, opposingPt, tickData, info, hinting); } else if (this.tickLabelOrientation.equals( LabelOrientation.PARALLEL)) { maxTickLabelDim = drawParallelTickLabels(g2, axisLine, opposingPt, tickData, maxTickLabelWidth, info, hinting); } } else { maxTickLabelDim = 0.0; } // draw the axis label if there is one if (getLabel() != null) { Shape labelBounds = drawAxisLabel(getLabel(), g2, axisLine, opposingPt, maxTickLabelDim + this.tickMarkLength + this.tickLabelOffset + getLabelOffset(), info, hinting); } } /** * Returns "row" if the axis has been configured as a row axis, "column" if * the axis has been configured as a column axis, and the empty string ("") * if the axis has not yet been configured. * * @return A string (never {@code null}). * * @since 1.3 */ @Override protected String axisStr() { String result = ""; if (this.isRowAxis) { result = "row"; } else if (this.isColumnAxis) { result = "column"; } return result; } private double drawParallelTickLabels(Graphics2D g2, Line2D axisLine, Point2D opposingPt, List tickData, double maxTickLabelWidth, RenderingInfo info, boolean hinting) { int levels = 1; LineMetrics lm = g2.getFontMetrics().getLineMetrics("123", g2); double height = lm.getHeight(); if (tickData.size() > 1) { // work out how many offset levels we need to display the // categories without overlapping Point2D p0 = tickData.get(0).getAnchorPt(); Point2D pN = tickData.get(tickData.size() - 1).getAnchorPt(); double availableWidth = pN.distance(p0) * tickData.size() / (tickData.size() - 1); int labelsPerLevel = (int) Math.floor(availableWidth / (maxTickLabelWidth * tickLabelFactor)); int levelsRequired = this.maxTickLabelLevels; if (labelsPerLevel > 0) { levelsRequired = this.categories.size() / labelsPerLevel + 1; } levels = Math.min(levelsRequired, this.maxTickLabelLevels); } int index = 0; for (TickData t : tickData) { int level = index % levels; double adj = height * (level + 0.5); Line2D perpLine = Utils2D.createPerpendicularLine(axisLine, t.getAnchorPt(), this.tickMarkLength + this.tickLabelOffset + adj, opposingPt); double axisTheta = Utils2D.calculateTheta(axisLine); TextAnchor textAnchor = TextAnchor.CENTER; if (axisTheta >= Math.PI / 2.0) { axisTheta = axisTheta - Math.PI; } else if (axisTheta <= -Math.PI / 2) { axisTheta = axisTheta + Math.PI; } String tickLabel = t.getKeyLabel(); if (hinting) { Map m = new HashMap<>(); m.put("ref", "{\"type\": \"categoryTickLabel\", \"axis\": \"" + axisStr() + "\", \"key\": \"" + t.getKey() + "\"}"); g2.setRenderingHint(Chart3DHints.KEY_BEGIN_ELEMENT, m); } Shape bounds = TextUtils.drawRotatedString(tickLabel, g2, (float) perpLine.getX2(), (float) perpLine.getY2(), textAnchor, axisTheta, textAnchor); if (hinting) { g2.setRenderingHint(Chart3DHints.KEY_END_ELEMENT, true); } if (info != null) { RenderedElement tickLabelElement = new RenderedElement( InteractiveElementType.CATEGORY_AXIS_TICK_LABEL, bounds); tickLabelElement.setProperty("label", tickLabel); tickLabelElement.setProperty("axis", axisStr()); info.addOffsetElement(tickLabelElement); } index++; } return height * levels; } /** * Draws the category labels perpendicular to the axis. * * @param g2 the graphics target. * @param axisLine the axis line. * @param opposingPt an opposing point (used to indicate which side the * labels will appear on). * @param tickData the tick data. * @param info if not {@code null} this will be populated with * {@link RenderedElement} instances for the tick labels. * @param hinting */ @SuppressWarnings("unchecked") private void drawPerpendicularTickLabels(Graphics2D g2, Line2D axisLine, Point2D opposingPt, List tickData, RenderingInfo info, boolean hinting) { for (TickData t : tickData) { Line2D perpLine = Utils2D.createPerpendicularLine(axisLine, t.getAnchorPt(), this.tickMarkLength + this.tickLabelOffset, opposingPt); double perpTheta = Utils2D.calculateTheta(perpLine); TextAnchor textAnchor = TextAnchor.CENTER_LEFT; if (perpTheta >= Math.PI / 2.0) { perpTheta = perpTheta - Math.PI; textAnchor = TextAnchor.CENTER_RIGHT; } else if (perpTheta <= -Math.PI / 2) { perpTheta = perpTheta + Math.PI; textAnchor = TextAnchor.CENTER_RIGHT; } String tickLabel = t.getKeyLabel(); if (hinting) { Map m = new HashMap(); m.put("ref", "{\"type\": \"categoryAxisLabel\", \"axis\": \"" + axisStr() + "\", \"key\": \"" + t.getKey() + "\"}"); g2.setRenderingHint(Chart3DHints.KEY_BEGIN_ELEMENT, m); } Shape bounds = TextUtils.drawRotatedString(tickLabel, g2, (float) perpLine.getX2(), (float) perpLine.getY2(), textAnchor, perpTheta, textAnchor); if (hinting) { g2.setRenderingHint(Chart3DHints.KEY_END_ELEMENT, true); } if (info != null) { RenderedElement tickLabelElement = new RenderedElement( InteractiveElementType.CATEGORY_AXIS_TICK_LABEL, bounds); tickLabelElement.setProperty("label", tickLabel); tickLabelElement.setProperty("axis", axisStr()); info.addOffsetElement(tickLabelElement); } } } /** * Generates the tick data for the axis (assumes the axis is being used * as the row axis). The dataset is passed as an argument to provide the * opportunity to incorporate dataset-specific info into tick labels (for * example, a row label might show the total for that row in the dataset) * ---whether or not this is used depends on the axis implementation. * * @param dataset the dataset ({@code null} not permitted). * * @return The tick data. * * @since 1.2 */ @Override @SuppressWarnings("unchecked") public List generateTickDataForRows(CategoryDataset3D dataset) { Args.nullNotPermitted(dataset, "dataset"); List result = new ArrayList<>(this.categories.size()); for (Comparable key : this.categories) { double pos = this.range.percent(getCategoryValue(key)); String label = this.tickLabelGenerator.generateRowLabel(dataset, key); result.add(new TickData(pos, key, label)); } return result; } /** * Generates the tick data for the axis (assumes the axis is being used * as the row axis). The dataset is passed as an argument to provide the * opportunity to incorporate dataset-specific info into tick labels (for * example, a row label might show the total for that row in the dataset) * ---whether or not this is used depends on the axis implementation. * * @param dataset the dataset ({@code null} not permitted). * * @return The tick data. * * @since 1.2 */ @Override @SuppressWarnings("unchecked") public List generateTickDataForColumns( CategoryDataset3D dataset) { Args.nullNotPermitted(dataset, "dataset"); List result = new ArrayList<>(this.categories.size()); for (Comparable key : this.categories) { double pos = this.range.percent(getCategoryValue(key)); String label = this.tickLabelGenerator.generateColumnLabel(dataset, key); result.add(new TickData(pos, key, label)); } return result; } /** * Generates and returns a list of marker data items for the axis. * * @return A list of marker data items (never {@code null}). */ @Override public List generateMarkerData() { List result = new ArrayList<>(); for (Map.Entry entry : this.markers.entrySet()) { CategoryMarker cm = entry.getValue(); if (cm == null) { continue; } MarkerData markerData; if (cm.getType().equals(CategoryMarkerType.LINE)) { double pos = getCategoryValue(cm.getCategory()); markerData = new MarkerData(entry.getKey(), pos); markerData.setLabelAnchor(cm.getLabel() != null ? cm.getLabelAnchor() : null); } else if (cm.getType().equals(CategoryMarkerType.BAND)) { double pos = getCategoryValue(cm.getCategory()); double width = getCategoryWidth(); markerData = new MarkerData(entry.getKey(), pos - width / 2, false, pos + width / 2, false); markerData.setLabelAnchor(cm.getLabel() != null ? cm.getLabelAnchor() : null); } else { throw new RuntimeException("Unrecognised marker: " + cm.getType()); } result.add(markerData); } return result; } /** * Receives a {@link ChartElementVisitor}. This method is part of a general * mechanism for traversing the chart structure and performing operations * on each element in the chart. You will not normally call this method * directly. * * @param visitor the visitor ({@code null} not permitted). * * @since 1.2 */ @Override public void receive(ChartElementVisitor visitor) { for (Marker marker : this.markers.values()) { marker.receive(visitor); } visitor.visit(this); } /** * Tests this instance for equality with an arbitrary object. * * @param obj the object to test against ({@code null} not permitted). * * @return A boolean. */ @Override public boolean equals(Object obj) { if (obj == this) { return true; } if (!(obj instanceof StandardCategoryAxis3D)) { return false; } StandardCategoryAxis3D that = (StandardCategoryAxis3D) obj; if (this.lowerMargin != that.lowerMargin) { return false; } if (this.upperMargin != that.upperMargin) { return false; } if (this.firstCategoryHalfWidth != that.firstCategoryHalfWidth) { return false; } if (this.lastCategoryHalfWidth != that.lastCategoryHalfWidth) { return false; } if (this.tickMarkLength != that.tickMarkLength) { return false; } if (!ObjectUtils.equalsPaint(this.tickMarkPaint, that.tickMarkPaint)) { return false; } if (!this.tickMarkStroke.equals(that.tickMarkStroke)) { return false; } if (!this.tickLabelGenerator.equals(that.tickLabelGenerator)) { return false; } if (this.tickLabelOffset != that.tickLabelOffset) { return false; } if (!this.tickLabelOrientation.equals(that.tickLabelOrientation)) { return false; } if (this.tickLabelFactor != that.tickLabelFactor) { return false; } if (this.maxTickLabelLevels != that.maxTickLabelLevels) { return false; } if (!this.markers.equals(that.markers)) { return false; } return super.equals(obj); } /** * Provides serialization support. * * @param stream the output stream. * * @throws IOException if there is an I/O error. */ private void writeObject(ObjectOutputStream stream) throws IOException { stream.defaultWriteObject(); SerialUtils.writePaint(this.tickMarkPaint, stream); SerialUtils.writeStroke(this.tickMarkStroke, stream); } /** * Provides serialization support. * * @param stream the input stream. * * @throws IOException if there is an I/O error. * @throws ClassNotFoundException if there is a classpath problem. */ private void readObject(ObjectInputStream stream) throws IOException, ClassNotFoundException { stream.defaultReadObject(); this.tickMarkPaint = SerialUtils.readPaint(stream); this.tickMarkStroke = SerialUtils.readStroke(stream); } /** * Returns {@code true} if the axis inverts the order of the data items, * and {@code false} otherwise. * * @return A boolean. * * @since 1.5 */ @Override public boolean isInverted() { return this.inverted; } /** * Sets the flag that controls whether or not the axis inverts the order * of the data items and sends an {@link Axis3DChangeEvent} to all * registered listeners. * * @param inverted the new flag value. * * @since 1.5 */ @Override public void setInverted(boolean inverted) { this.inverted = inverted; fireChangeEvent(true); } } orson-charts-2.1.0/src/main/java/org/jfree/chart3d/axis/TickData.java000066400000000000000000000130611417331271500253020ustar00rootroot00000000000000/* =========================================================== * Orson Charts : a 3D chart library for the Java(tm) platform * =========================================================== * * (C)opyright 2013-2022, by David Gilbert. All rights reserved. * * https://github.com/jfree/orson-charts * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . * * [Oracle and Java are registered trademarks of Oracle and/or its affiliates. * Other names may be trademarks of their respective owners.] * * If you do not wish to be bound by the terms of the GPL, an alternative * commercial license can be purchased. For details, please see visit the * Orson Charts home page: * * http://www.object-refinery.com/orsoncharts/index.html * */ package org.jfree.chart3d.axis; import java.awt.geom.Point2D; import org.jfree.chart3d.internal.Args; /** * Data related to the tick marks and labels on a chart. */ public class TickData { /** The position along the axis as a percentage. */ private final double pos; /** The key for the tick (used for CategoryAxis3D, null otherwise). */ private final Comparable key; /** * The label used for the category key (used for CategoryAxis3D, null * otherwise). */ private final String keyLabel; /** The data value (used for ValueAxis3D). */ private final double dataValue; /** The vertex in the ChartBox that is the anchor point for this tick. */ private int vertexIndex; /** The anchor point. */ private Point2D anchorPt; /** * Creates a new instance. This constructor is used for category axes. * * @param pos the position along the axis as a percentage of the range. * @param key the key. * @param keyLabel the key label. */ public TickData(double pos, Comparable key, String keyLabel) { this.pos = pos; this.key = key; this.keyLabel = keyLabel; this.dataValue = Double.NaN; this.vertexIndex = -1; this.anchorPt = null; } /** * Creates a new instance. This constructor is used for numerical axes. * * @param pos the position along the axis as a percentage of the range. * @param dataValue the data value. */ public TickData(double pos, double dataValue) { this.pos = pos; this.dataValue = dataValue; this.key = null; this.keyLabel = null; this.vertexIndex = -1; this.anchorPt = null; } /** * Creates a new instance by copying an existing instance but altering * the vertex index. * * @param source a source to copy ({@code null} not permitted). * @param vertexIndex the vertex index. */ public TickData(TickData source, int vertexIndex) { Args.nullNotPermitted(source, "source"); this.pos = source.pos; this.dataValue = source.dataValue; this.key = source.key; this.keyLabel = source.keyLabel; this.anchorPt = source.anchorPt; this.vertexIndex = vertexIndex; } /** * Returns the position of the tick, as a percentage along the axis (for * example, 0.5 is halfway along the axis). * * @return The position. */ public double getPos() { return this.pos; } /** * Returns the key when the tick data is for a {@link CategoryAxis3D}, * and {@code null} otherwise. * * @return The key (possibly {@code null}). */ public Comparable getKey() { return this.key; } /** * Returns the key label. * * @return The key label (possibly {@code null}). * * @since 1.2 */ public String getKeyLabel() { return this.keyLabel; } /** * Returns the data value when the tick data is for a {@link NumberAxis3D}, * and {@code Double.NaN} otherwise. * * @return The data value. */ public double getDataValue() { return this.dataValue; } /** * Returns the vertex index that is the anchor point for the tick mark. * * @return The vertex index. */ public int getVertexIndex() { return this.vertexIndex; } /** * Sets the vertex index. The vertex is a point in 3D space that is * the anchor point for the tick mark, after this is projected to * 2D space we have a reference point for the tick mark. * * @param index the index. */ public void setVertexIndex(int index) { this.vertexIndex = index; } /** * Returns the anchor point. * * @return The anchor point. */ public Point2D getAnchorPt() { return this.anchorPt; } /** * Sets the anchor point. This is the projected point in 2D space of the * vertex we track in 3D space. * * @param anchorPt the anchor point. */ public void setAnchorPt(Point2D anchorPt) { this.anchorPt = anchorPt; } } orson-charts-2.1.0/src/main/java/org/jfree/chart3d/axis/TickSelector.java000066400000000000000000000101061417331271500262060ustar00rootroot00000000000000/* =========================================================== * Orson Charts : a 3D chart library for the Java(tm) platform * =========================================================== * * (C)opyright 2013-2022, by David Gilbert. All rights reserved. * * https://github.com/jfree/orson-charts * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . * * [Oracle and Java are registered trademarks of Oracle and/or its affiliates. * Other names may be trademarks of their respective owners.] * * If you do not wish to be bound by the terms of the GPL, an alternative * commercial license can be purchased. For details, please see visit the * Orson Charts home page: * * http://www.object-refinery.com/orsoncharts/index.html * */ package org.jfree.chart3d.axis; import java.text.Format; /** *

Provides standard tick sizes and formatting for numerical axes. * Conceptually, the selector maintains a list of standard tick sizes (ordered * by size), and a pointer to the current (selected) tick size. Clients of * the selector will initialise the pointer by calling the * {@link #select(double)} method with a reference value (a guess, based on * context, of the largest usable tick size - for example, one half of the * axis length) then, as required, move the pointer to a smaller or larger * tick size (using the {@link #next()} and {@link #previous()} methods) to * find the most appropriate standard size to use.

* *

The {@link NumberTickSelector} class provides a standard implementation, * but you can create your own if necessary.

*/ public interface TickSelector { /** * Selects and returns a standard tick size that is greater than or equal to * the specified reference value and, ideally, as close to it as possible * (to minimise the number of iterations used by axes to determine the tick * size to use). After a call to this method, the * {@link #getCurrentTickSize()} method should return the selected tick * size (there is a "cursor" that points to this tick size), the * {@link #next()} method should move the pointer to the next (larger) * standard tick size, and the {@link #previous()} method should move the * pointer to the previous (smaller) standard tick size. * * @param reference the reference value (must be positive and finite). * * @return The selected tick size. */ double select(double reference); /** * Move the cursor to the next (larger) tick size, if there is one. * Returns {@code true} in the case that the cursor is moved, and * {@code false} where there are a finite number of tick sizes and the * current tick size is the largest available. * * @return A boolean. */ boolean next(); /** * Move the cursor to the previous (smaller) tick size, if there is one. * Returns {@code true} in the case that the cursor is moved, and * {@code false} where there are a finite number of tick sizes and the * current tick size is the smallest available. * * @return A boolean. */ boolean previous(); /** * Returns the tick size that the cursor is currently referencing. * * @return The tick size. */ double getCurrentTickSize(); /** * Returns the tick formatter associated with the tick size that the * cursor is currently referencing. * * @return The formatter. */ Format getCurrentTickLabelFormat(); } orson-charts-2.1.0/src/main/java/org/jfree/chart3d/axis/ValueAxis3D.java000066400000000000000000000106251417331271500257110ustar00rootroot00000000000000/* =========================================================== * Orson Charts : a 3D chart library for the Java(tm) platform * =========================================================== * * (C)opyright 2013-2022, by David Gilbert. All rights reserved. * * https://github.com/jfree/orson-charts * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . * * [Oracle and Java are registered trademarks of Oracle and/or its affiliates. * Other names may be trademarks of their respective owners.] * * If you do not wish to be bound by the terms of the GPL, an alternative * commercial license can be purchased. For details, please see visit the * Orson Charts home page: * * http://www.object-refinery.com/orsoncharts/index.html * */ package org.jfree.chart3d.axis; import java.awt.Graphics2D; import java.awt.geom.Point2D; import java.util.List; import org.jfree.chart3d.marker.MarkerData; import org.jfree.chart3d.marker.ValueMarker; import org.jfree.chart3d.plot.CategoryPlot3D; import org.jfree.chart3d.plot.XYZPlot; /** * An axis that displays a range of continuous values. These can be used * for the value axis in a {@link CategoryPlot3D}, and for the X, Y or Z * axes in an {@link XYZPlot}. */ public interface ValueAxis3D extends Axis3D { /** * Returns the type of use that the axis has been configured for. * * @return The type (or {@code null} if the axis has not yet been * configured). * * @since 1.3 */ ValueAxis3DType getConfiguredType(); /** * Configure the axis as a value axis for the specified plot. * * @param plot the plot ({@code null} not permitted). */ void configureAsValueAxis(CategoryPlot3D plot); /** * Configure the axis as an x-axis for the specified plot. * * @param plot the plot ({@code null} not permitted). */ void configureAsXAxis(XYZPlot plot); /** * Configure the axis as a y-axis for the specified plot. * * @param plot the plot ({@code null} not permitted). */ void configureAsYAxis(XYZPlot plot); /** * Configure the axis as an z-axis for the specified plot. * * @param plot the plot ({@code null} not permitted). */ void configureAsZAxis(XYZPlot plot); /** * Selects an appropriate tick size and format for the axis based on * the axis being rendered from {@code pt0} to {@code pt1}. * * @param g2 the graphics target. * @param pt0 the starting point. * @param pt1 the ending point. * @param opposingPt a point on the opposite side of the axis from the * labels. * * @return The tick size. */ double selectTick(Graphics2D g2, Point2D pt0, Point2D pt1, Point2D opposingPt); /** * Generates a list of tick data items for the specified tick unit. This * data will be passed to the 3D engine and will be updated with a 2D * projection that can later be used to write the axis tick labels in the * appropriate places. *

* If {@code tickUnit} is {@code Double.NaN}, then tick data is * generated for just the bounds of the axis. * * @param tickUnit the tick unit. * * @return A list of tick data (never {@code null}). */ List generateTickData(double tickUnit); /** * Returns a list of marker data instances for the markers that fall * within the current axis range. * * @return A list of marker data. */ List generateMarkerData(); /** * Returns the marker with the specified key, if there is one. * * @param key the key ({@code null} not permitted). * * @return The marker (possibly {@code null}). * * @since 1.2 */ ValueMarker getMarker(String key); } orson-charts-2.1.0/src/main/java/org/jfree/chart3d/axis/ValueAxis3DType.java000066400000000000000000000035371417331271500265570ustar00rootroot00000000000000/* =========================================================== * Orson Charts : a 3D chart library for the Java(tm) platform * =========================================================== * * (C)opyright 2013-2022, by David Gilbert. All rights reserved. * * https://github.com/jfree/orson-charts * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . * * [Oracle and Java are registered trademarks of Oracle and/or its affiliates. * Other names may be trademarks of their respective owners.] * * If you do not wish to be bound by the terms of the GPL, an alternative * commercial license can be purchased. For details, please see visit the * Orson Charts home page: * * http://www.object-refinery.com/orsoncharts/index.html * */ package org.jfree.chart3d.axis; import org.jfree.chart3d.plot.CategoryPlot3D; import org.jfree.chart3d.plot.XYZPlot; /** * An enumeration of the value axis types. A {@link ValueAxis3D} can be * used in several different plot dimensions. * * @since 1.3 */ public enum ValueAxis3DType { /** A value axis in a {@link CategoryPlot3D}. */ VALUE, /** An x-axis in an {@link XYZPlot}. */ X, /** A y-axis in an {@link XYZPlot}. */ Y, /** A z-axis in an {@link XYZPlot}. */ Z } orson-charts-2.1.0/src/main/java/org/jfree/chart3d/axis/package-info.java000066400000000000000000000003561417331271500261450ustar00rootroot00000000000000/** * Axes ({@link org.jfree.chart3d.axis.CategoryAxis3D}, * {@link org.jfree.chart3d.axis.NumberAxis3D} and * {@link org.jfree.chart3d.axis.LogAxis3D}) plus supporting classes and * interfaces. */ package org.jfree.chart3d.axis; orson-charts-2.1.0/src/main/java/org/jfree/chart3d/data/000077500000000000000000000000001417331271500227175ustar00rootroot00000000000000orson-charts-2.1.0/src/main/java/org/jfree/chart3d/data/AbstractDataset3D.java000066400000000000000000000134011417331271500270210ustar00rootroot00000000000000/* =========================================================== * Orson Charts : a 3D chart library for the Java(tm) platform * =========================================================== * * (C)opyright 2013-2022, by David Gilbert. All rights reserved. * * https://github.com/jfree/orson-charts * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . * * [Oracle and Java are registered trademarks of Oracle and/or its affiliates. * Other names may be trademarks of their respective owners.] * * If you do not wish to be bound by the terms of the GPL, an alternative * commercial license can be purchased. For details, please see visit the * Orson Charts home page: * * http://www.object-refinery.com/orsoncharts/index.html * */ package org.jfree.chart3d.data; import java.util.Arrays; import java.util.EventListener; import java.util.List; import javax.swing.event.EventListenerList; /** * A base class that can be used to create new dataset classes. */ public class AbstractDataset3D implements Dataset3D { /** Storage for registered change listeners. */ private final transient EventListenerList listenerList; /** * A flag that controls whether or not the dataset will notify listeners * of changes (defaults to {@code true}, but sometimes it is useful * to disable this). */ private boolean notify; /** * Default constructor - allocates storage for listeners that can * be registered with the dataset. */ protected AbstractDataset3D() { this.listenerList = new EventListenerList(); this.notify = true; } /** * Returns a flag that controls whether or not change events are sent to * registered listeners. * * @return A boolean. * * @see #setNotify(boolean) */ public boolean isNotify() { return this.notify; } /** * Sets a flag that controls whether or not listeners receive * {@link Dataset3DChangeEvent} notifications. * * @param notify a boolean. * * @see #isNotify() */ public void setNotify(boolean notify) { this.notify = notify; // if the flag is being set to true, there may be queued up changes... if (notify) { fireChangeEvent(); } } /** * Registers an object to receive notification of changes to the dataset. * * @param listener the object to register. * * @see #removeChangeListener(Dataset3DChangeListener) */ @Override public void addChangeListener(Dataset3DChangeListener listener) { this.listenerList.add(Dataset3DChangeListener.class, listener); } /** * Deregisters an object so that it no longer receives notification of * changes to the dataset. * * @param listener the object to deregister. * * @see #addChangeListener(Dataset3DChangeListener) */ @Override public void removeChangeListener(Dataset3DChangeListener listener) { this.listenerList.remove(Dataset3DChangeListener.class, listener); } /** * Returns {@code true} if the specified object is registered with * the dataset as a listener. Most applications won't need to call this * method, it exists mainly for use by unit testing code. * * @param listener the listener. * * @return A boolean. * * @see #addChangeListener(Dataset3DChangeListener) * @see #removeChangeListener(Dataset3DChangeListener) */ @Override public boolean hasListener(EventListener listener) { List list = Arrays.asList(this.listenerList.getListenerList()); return list.contains(listener); } /** * Notifies all registered listeners that the dataset has changed. * * @see #addChangeListener(Dataset3DChangeListener) */ protected void fireDatasetChanged() { notifyListeners(new Dataset3DChangeEvent(this, this)); } /** * Notifies all registered listeners that the dataset has changed, unless * the {@code notify} flag is set to {@code false} in which * case this method does nothing. * * @param event contains information about the event that triggered the * notification. * * @see #addChangeListener(Dataset3DChangeListener) * @see #removeChangeListener(Dataset3DChangeListener) */ protected void notifyListeners(Dataset3DChangeEvent event) { // if the 'notify' flag has been switched to false, we don't notify // the listeners if (!this.notify) { return; } Object[] listeners = this.listenerList.getListenerList(); for (int i = listeners.length - 2; i >= 0; i -= 2) { if (listeners[i] == Dataset3DChangeListener.class) { ((Dataset3DChangeListener) listeners[i + 1]) .datasetChanged(event); } } } /** * Sends a {@link Dataset3DChangeEvent} to all registered listeners, unless * the {@code notify} flag is set to {@code false} in which * case this method does nothing. */ protected void fireChangeEvent() { notifyListeners(new Dataset3DChangeEvent(this, this)); } } orson-charts-2.1.0/src/main/java/org/jfree/chart3d/data/DataUtils.java000066400000000000000000001130441417331271500254570ustar00rootroot00000000000000/* =========================================================== * Orson Charts : a 3D chart library for the Java(tm) platform * =========================================================== * * (C)opyright 2013-2022, by David Gilbert. All rights reserved. * * https://github.com/jfree/orson-charts * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . * * [Oracle and Java are registered trademarks of Oracle and/or its affiliates. * Other names may be trademarks of their respective owners.] * * If you do not wish to be bound by the terms of the GPL, an alternative * commercial license can be purchased. For details, please see visit the * Orson Charts home page: * * http://www.object-refinery.com/orsoncharts/index.html * */ package org.jfree.chart3d.data; import java.util.List; import org.jfree.chart3d.data.category.CategoryDataset3D; import org.jfree.chart3d.data.xyz.XYZDataset; import org.jfree.chart3d.data.xyz.XYZSeries; import org.jfree.chart3d.data.xyz.XYZSeriesCollection; import org.jfree.chart3d.internal.Args; /** * Some utility methods for working with the various datasets and data * structures available in Orson Charts. */ public class DataUtils { private DataUtils() { // no need to create instances } /** * Returns the total of the values in the list. Any {@code null} * values are ignored. * * @param values the values ({@code null} not permitted). * * @return The total of the values in the list. */ public static double total(Values values) { double result = 0.0; for (int i = 0; i < values.getItemCount(); i++) { Number n = values.getValue(i); if (n != null) { result = result + n.doubleValue(); } } return result; } /** * Returns the count of the non-{@code null} entries in the dataset * for the specified series. An {@code IllegalArgumentException} is * thrown if the {@code seriesKey} is not present in the data. * * @param the series key (must implement Comparable). * @param data the dataset ({@code null} not permitted). * @param seriesKey the series key ({@code null} not permitted). * * @return The count. * * @since 1.2 */ public static > int count( KeyedValues3D data, S seriesKey) { Args.nullNotPermitted(data, "data"); Args.nullNotPermitted(seriesKey, "seriesKey"); int seriesIndex = data.getSeriesIndex(seriesKey); if (seriesIndex < 0) { throw new IllegalArgumentException("Series not found: " + seriesKey); } int count = 0; int rowCount = data.getRowCount(); int columnCount = data.getColumnCount(); for (int r = 0; r < rowCount; r++) { for (int c = 0; c < columnCount; c++) { Number n = (Number) data.getValue(seriesIndex, r, c); if (n != null) { count++; } } } return count; } /** * Returns the count of the non-{@code null} entries in the dataset * for the specified row (all series). * * @param the row key (must implement Comparable). * @param data the dataset ({@code null} not permitted). * @param rowKey the row key ({@code null} not permitted). * * @return The count. * * @since 1.2 */ public static > int countForRow( KeyedValues3D data, R rowKey) { Args.nullNotPermitted(data, "data"); Args.nullNotPermitted(rowKey, "rowKey"); int rowIndex = data.getRowIndex(rowKey); if (rowIndex < 0) { throw new IllegalArgumentException("Row not found: " + rowKey); } int count = 0; int seriesCount = data.getSeriesCount(); int columnCount = data.getColumnCount(); for (int s = 0; s < seriesCount; s++) { for (int c = 0; c < columnCount; c++) { Number n = (Number) data.getValue(s, rowIndex, c); if (n != null) { count++; } } } return count; } /** * Returns the count of the non-{@code null} entries in the dataset * for the specified column (all series). * * @param the column key (must implement Comparable). * @param data the dataset ({@code null} not permitted). * @param columnKey the column key ({@code null} not permitted). * * @return The count. * * @since 1.2 */ public static > int countForColumn( KeyedValues3D data, C columnKey) { Args.nullNotPermitted(data, "data"); Args.nullNotPermitted(columnKey, "columnKey"); int columnIndex = data.getColumnIndex(columnKey); if (columnIndex < 0) { throw new IllegalArgumentException("Column not found: " + columnKey); } int count = 0; int seriesCount = data.getSeriesCount(); int rowCount = data.getRowCount(); for (int s = 0; s < seriesCount; s++) { for (int r = 0; r < rowCount; r++) { Number n = (Number) data.getValue(s, r, columnIndex); if (n != null) { count++; } } } return count; } /** * Returns the total of the non-{@code null} values in the dataset * for the specified series. If there is no series with the specified * key, this method will throw an {@code IllegalArgumentException}. * * @param the series key (must implement Comparable). * @param data the dataset ({@code null} not permitted). * @param seriesKey the series key ({@code null} not permitted). * * @return The total. * * @since 1.2 */ public static > double total( KeyedValues3D data, S seriesKey) { Args.nullNotPermitted(data, "data"); Args.nullNotPermitted(seriesKey, "seriesKey"); int seriesIndex = data.getSeriesIndex(seriesKey); if (seriesIndex < 0) { throw new IllegalArgumentException("Series not found: " + seriesKey); } double total = 0.0; int rowCount = data.getRowCount(); int columnCount = data.getColumnCount(); for (int r = 0; r < rowCount; r++) { for (int c = 0; c < columnCount; c++) { Number n = data.getValue(seriesIndex, r, c); if (n != null) { total += n.doubleValue(); } } } return total; } /** * Returns the total of the non-{@code null} entries in the dataset * for the specified row (all series). * * @param the row key (must implement Comparable). * @param data the dataset ({@code null} not permitted). * @param rowKey the row key ({@code null} not permitted). * * @return The total. * * @since 1.2 */ public static > double totalForRow( KeyedValues3D data, R rowKey) { Args.nullNotPermitted(data, "data"); Args.nullNotPermitted(rowKey, "rowKey"); int rowIndex = data.getRowIndex(rowKey); if (rowIndex < 0) { throw new IllegalArgumentException("Row not found: " + rowKey); } double total = 0.0; int seriesCount = data.getSeriesCount(); int columnCount = data.getColumnCount(); for (int s = 0; s < seriesCount; s++) { for (int c = 0; c < columnCount; c++) { Number n = data.getValue(s, rowIndex, c); if (n != null) { total += n.doubleValue(); } } } return total; } /** * Returns the total of the non-{@code null} entries in the dataset * for the specified column (all series). * * @param the column key (must implement Comparable). * @param data the dataset ({@code null} not permitted). * @param columnKey the row key ({@code null} not permitted). * * @return The total. * * @since 1.2 */ public static > double totalForColumn( KeyedValues3D data, C columnKey) { Args.nullNotPermitted(data, "data"); Args.nullNotPermitted(columnKey, "columnKey"); int columnIndex = data.getColumnIndex(columnKey); if (columnIndex < 0) { throw new IllegalArgumentException("Column not found: " + columnKey); } double total = 0.0; int seriesCount = data.getSeriesCount(); int rowCount = data.getRowCount(); for (int s = 0; s < seriesCount; s++) { for (int r = 0; r < rowCount; r++) { Number n = data.getValue(s, r, columnIndex); if (n != null) { total += n.doubleValue(); } } } return total; } /** * Returns the range of values in the specified data structure (a three * dimensional cube). If there is no data, this method returns * {@code null}. * * @param data the data ({@code null} not permitted). * * @return The range of data values (possibly {@code null}). */ public static Range findValueRange(Values3D data) { return findValueRange(data, Double.NaN); } /** * Returns the range of values in the specified data cube, or * {@code null} if there is no data. The range will be expanded, if * required, to include the {@code base} value (unless it * is {@code Double.NaN} in which case it is ignored). * * @param data the data ({@code null} not permitted). * @param base a value that must be included in the range (often 0). This * argument is ignored if it is {@code Double.NaN}. * * @return The range (possibly {@code null}). */ public static Range findValueRange(Values3D data, double base) { return findValueRange(data, base, true); } /** /** * Returns the range of values in the specified data cube, or * {@code null} if there is no data. The range will be expanded, if * required, to include the {@code base} value (unless it * is {@code Double.NaN} in which case it is ignored). * * @param data the data ({@code null} not permitted). * @param base a value that must be included in the range (often 0). This * argument is ignored if it is {@code Double.NaN}. * @param finite if {@code true} infinite values will be ignored. * * @return The range (possibly {@code null}). * * @since 1.4 */ public static Range findValueRange(Values3D data, double base, boolean finite) { Args.nullNotPermitted(data, "data"); double min = Double.POSITIVE_INFINITY; double max = Double.NEGATIVE_INFINITY; for (int series = 0; series < data.getSeriesCount(); series++) { for (int row = 0; row < data.getRowCount(); row++) { for (int col = 0; col < data.getColumnCount(); col++) { double d = data.getDoubleValue(series, row, col); if (!Double.isNaN(d)) { if (!finite || !Double.isInfinite(d)) { min = Math.min(min, d); max = Math.max(max, d); } } } } } // include the special value in the range if (!Double.isNaN(base)) { min = Math.min(min, base); max = Math.max(max, base); } if (min <= max) { return new Range(min, max); } else { return null; } } /** * Finds the range of values in the dataset considering that each series * is stacked on top of the other. * * @param data the data ({@code null} not permitted). * * @return The range. */ public static Range findStackedValueRange(Values3D data) { return findStackedValueRange(data, 0.0); } /** * Finds the range of values in the dataset considering that each series * is stacked on top of the others, starting at the base value. * * @param data the data values ({@code null} not permitted). * @param base the base value. * * @return The range. */ public static Range findStackedValueRange(Values3D data, double base) { Args.nullNotPermitted(data, "data"); double min = base; double max = base; int seriesCount = data.getSeriesCount(); for (int row = 0; row < data.getRowCount(); row++) { for (int col = 0; col < data.getColumnCount(); col++) { double[] total = stackSubTotal(data, base, seriesCount, row, col); min = Math.min(min, total[0]); max = Math.max(max, total[1]); } } if (min <= max) { return new Range(min, max); } else { return null; } } /** * Returns the positive and negative subtotals of the values for all the * series preceding the specified series. *

* One application for this method is to compute the base values for * individual bars in a stacked bar chart. * * @param data the data ({@code null} not permitted). * @param base the initial base value (normally {@code 0.0}, but the * values can be stacked from a different starting point). * @param series the index of the current series (series with lower indices * are included in the sub-totals). * @param row the row index of the required item. * @param column the column index of the required item. * * @return The subtotals, where {@code result[0]} is the subtotal of * the negative data items, and {@code result[1]} is the subtotal * of the positive data items. */ public static double[] stackSubTotal(Values3D data, double base, int series, int row, int column) { double neg = base; double pos = base; for (int s = 0; s < series; s++) { double v = data.getDoubleValue(s, row, column); if (v > 0.0) { pos = pos + v; } else if (v < 0.0) { neg = neg + v; } } return new double[] { neg, pos }; } /** * Returns the total of the non-{@code NaN} entries in the dataset * for the specified series. * * @param the series key (must implement Comparable). * @param data the dataset ({@code null} not permitted). * @param seriesKey the series key ({@code null} not permitted). * * @return The count. * * @since 1.2 */ public static > double total(XYZDataset data, S seriesKey) { Args.nullNotPermitted(data, "data"); Args.nullNotPermitted(seriesKey, "seriesKey"); int seriesIndex = data.getSeriesIndex(seriesKey); if (seriesIndex < 0) { throw new IllegalArgumentException("Series not found: " + seriesKey); } double total = 0; int itemCount = data.getItemCount(seriesIndex); for (int item = 0; item < itemCount; item++) { double y = data.getY(seriesIndex, item); if (!Double.isNaN(y)) { total += y; } } return total; } /** * Returns the range of x-values in the dataset by iterating over all * values (and ignoring {@code Double.NaN} and infinite values). * If there are no values eligible for inclusion in the range, this method * returns {@code null}. * * @param dataset the dataset ({@code null} not permitted). * * @return The range (possibly {@code null}). */ public static Range findXRange(XYZDataset dataset) { return findXRange(dataset, Double.NaN); } /** * Returns the range of x-values in the dataset by iterating over all * values (and ignoring {@code Double.NaN} values). The range will be * extended if necessary to include {@code inc} (unless it is * {@code Double.NaN} in which case it is ignored). Infinite values * in the dataset will be ignored. If there are no values eligible for * inclusion in the range, this method returns {@code null}. * * @param dataset the dataset ({@code null} not permitted). * @param inc an additional x-value to include. * * @return The range (possibly {@code null}). */ public static Range findXRange(XYZDataset dataset, double inc) { return findXRange(dataset, inc, true); } /** * Returns the range of x-values in the dataset by iterating over all * values (and ignoring {@code Double.NaN} values). The range will be * extended if necessary to include {@code inc} (unless it is * {@code Double.NaN} in which case it is ignored). If the * {@code finite} flag is set, infinite values in the dataset will be * ignored. If there are no values eligible for inclusion in the range, * this method returns {@code null}. * * @param dataset the dataset ({@code null} not permitted). * @param inc an additional x-value to include. * @param finite a flag indicating whether to exclude infinite values. * * @return The range (possibly {@code null}). * * @since 1.4 */ public static Range findXRange(XYZDataset dataset, double inc, boolean finite) { Args.nullNotPermitted(dataset, "dataset"); double min = Double.POSITIVE_INFINITY; double max = Double.NEGATIVE_INFINITY; for (int s = 0; s < dataset.getSeriesCount(); s++) { for (int i = 0; i < dataset.getItemCount(s); i++) { double x = dataset.getX(s, i); if (!Double.isNaN(x)) { if (!finite || !Double.isInfinite(x)) { min = Math.min(x, min); max = Math.max(x, max); } } } } if (!Double.isNaN(inc)) { min = Math.min(inc, min); max = Math.max(inc, max); } if (min <= max) { return new Range(min, max); } else { return null; } } /** * Returns the range of y-values in the dataset by iterating over all * values (and ignoring {@code Double.NaN} and infinite values). * If there are no values eligible for inclusion in the range, this method * returns {@code null}. * * @param dataset the dataset ({@code null} not permitted). * * @return The range. */ public static Range findYRange(XYZDataset dataset) { return findYRange(dataset, Double.NaN); } /** * Returns the range of y-values in the dataset by iterating over all * values (and ignoring {@code Double.NaN} values). The range will be * extended if necessary to include {@code inc} (unless it is * {@code Double.NaN} in which case it is ignored). Infinite values * in the dataset will be ignored. If there are no values eligible for * inclusion in the range, this method returns {@code null}. * * @param dataset the dataset ({@code null} not permitted). * @param inc an additional x-value to include. * * @return The range. */ public static Range findYRange(XYZDataset dataset, double inc) { return findYRange(dataset, inc, true); } /** * Returns the range of y-values in the dataset by iterating over all * values (and ignoring {@code Double.NaN} values). The range will be * extended if necessary to include {@code inc} (unless it is * {@code Double.NaN} in which case it is ignored). If the * {@code finite} flag is set, infinite values in the dataset will be * ignored. If there are no values eligible for inclusion in the range, * this method returns {@code null}. * * @param dataset the dataset ({@code null} not permitted). * @param inc an additional y-value to include. * @param finite a flag indicating whether to exclude infinite values. * * @return The range (possibly {@code null}). * * @since 1.4 */ public static Range findYRange(XYZDataset dataset, double inc, boolean finite) { Args.nullNotPermitted(dataset, "dataset"); double min = Double.POSITIVE_INFINITY; double max = Double.NEGATIVE_INFINITY; for (int s = 0; s < dataset.getSeriesCount(); s++) { for (int i = 0; i < dataset.getItemCount(s); i++) { double y = dataset.getY(s, i); if (!Double.isNaN(y)) { if (!finite || !Double.isInfinite(y)) { min = Math.min(y, min); max = Math.max(y, max); } } } } if (!Double.isNaN(inc)) { min = Math.min(inc, min); max = Math.max(inc, max); } if (min <= max) { return new Range(min, max); } else { return null; } } /** * Returns the range of z-values in the dataset by iterating over all * values (and ignoring {@code Double.NaN} and infinite values). * If there are no values eligible for inclusion in the range, this method * returns {@code null}. * * @param dataset the dataset ({@code null} not permitted). * * @return The range (possibly {@code null}). */ public static Range findZRange(XYZDataset dataset) { return findZRange(dataset, Double.NaN); } /** * Returns the range of z-values in the dataset by iterating over all * values (and ignoring {@code Double.NaN} values). The range will be * extended if necessary to include {@code inc} (unless it is * {@code Double.NaN} in which case it is ignored). Infinite values * in the dataset will be ignored. If there are no values eligible for * inclusion in the range, this method returns {@code null}. * * @param dataset the dataset ({@code null} not permitted). * @param inc an additional x-value to include. * * @return The range (possibly {@code null}). */ public static Range findZRange(XYZDataset dataset, double inc) { return findZRange(dataset, inc, true); } /** * Returns the range of z-values in the dataset by iterating over all * values (and ignoring {@code Double.NaN} values). The range will be * extended if necessary to include {@code inc} (unless it is * {@code Double.NaN} in which case it is ignored). If the * {@code finite} flag is set, infinite values in the dataset will be * ignored. If there are no values eligible for inclusion in the range, * this method returns {@code null}. * * @param dataset the dataset ({@code null} not permitted). * @param inc an additional z-value to include. * @param finite a flag indicating whether to exclude infinite values. * * @return The range (possibly {@code null}). * * @since 1.4 */ public static Range findZRange(XYZDataset dataset, double inc, boolean finite) { Args.nullNotPermitted(dataset, "dataset"); Args.finiteRequired(inc, "inc"); double min = Double.POSITIVE_INFINITY; double max = Double.NEGATIVE_INFINITY; for (int s = 0; s < dataset.getSeriesCount(); s++) { for (int i = 0; i < dataset.getItemCount(s); i++) { double z = dataset.getZ(s, i); if (!Double.isNaN(z)) { if (!finite || !Double.isInfinite(z)) { min = Math.min(z, min); max = Math.max(z, max); } } } } if (!Double.isNaN(inc)) { min = Math.min(inc, min); max = Math.max(inc, max); } if (min <= max) { return new Range(min, max); } else { return null; } } /** * Creates an {@link XYZDataset} by extracting values from specified * rows in a {@link KeyedValues3D} instance, across all the available * columns (items where any of the x, y or z values is {@code null} * are skipped). The new dataset contains a copy of the data and is * completely independent of the {@code source} dataset. *

* Note that {@link CategoryDataset3D} is an extension of * {@link KeyedValues3D} so you can use this method for any implementation * of the {@code CategoryDataset3D} interface. * * @param the series key (must implement Comparable). * @param the row key (must implement Comparable). * @param the column key (must implement Comparable). * @param source the source data ({@code null} not permitted). * @param xRowKey the row key for x-values ({@code null} not permitted). * @param yRowKey the row key for y-values ({@code null} not permitted). * @param zRowKey the row key for z-values ({@code null} not permitted). * * @return A new dataset. * * @since 1.3 */ public static , R extends Comparable, C extends Comparable> XYZDataset extractXYZDatasetFromRows( KeyedValues3D source, R xRowKey, R yRowKey, R zRowKey) { return extractXYZDatasetFromRows(source, xRowKey, yRowKey, zRowKey, NullConversion.SKIP, null); } /** * Creates an {@link XYZDataset} by extracting values from specified * rows in a {@link KeyedValues3D} instance. The new dataset contains * a copy of the data and is completely independent of the * {@code source} dataset. Note that {@link CategoryDataset3D} is an * extension of {@link KeyedValues3D}. *

* Special handling is provided for items that contain {@code null} * values. The caller may pass in an {@code exceptions} list ( * normally empty) that will be populated with the keys of the items that * receive special handling, if any. * * @param the series key (must implement Comparable). * @param the row key (must implement Comparable). * @param the column key (must implement Comparable). * @param source the source data ({@code null} not permitted). * @param xRowKey the row key for x-values ({@code null} not permitted). * @param yRowKey the row key for y-values ({@code null} not permitted). * @param zRowKey the row key for z-values ({@code null} not permitted). * @param nullConversion specifies the treatment for {@code null} * values in the dataset ({@code null} not permitted). * @param exceptions a list that, if not null, will be populated with * keys for the items in the source dataset that contain * {@code null} values ({@code null} permitted). * * @return A new dataset. * * @since 1.3 */ public static , R extends Comparable, C extends Comparable> XYZDataset extractXYZDatasetFromRows( KeyedValues3D source, R xRowKey, R yRowKey, R zRowKey, NullConversion nullConversion, List exceptions) { Args.nullNotPermitted(source, "source"); Args.nullNotPermitted(xRowKey, "xRowKey"); Args.nullNotPermitted(yRowKey, "yRowKey"); Args.nullNotPermitted(zRowKey, "zRowKey"); XYZSeriesCollection dataset = new XYZSeriesCollection<>(); for (S seriesKey : source.getSeriesKeys()) { XYZSeries series = new XYZSeries<>(seriesKey); for (C colKey : source.getColumnKeys()) { Number x = source.getValue(seriesKey, xRowKey, colKey); Number y = source.getValue(seriesKey, yRowKey, colKey); Number z = source.getValue(seriesKey, zRowKey, colKey); if (x != null && y != null && z != null) { series.add(x.doubleValue(), y.doubleValue(), z.doubleValue()); } else { if (exceptions != null) { // add only one exception per data value R rrKey = zRowKey; if (x == null) { rrKey = xRowKey; } else if (y == null) { rrKey = yRowKey; } exceptions.add(new KeyedValues3DItemKey<>(seriesKey, rrKey, colKey)); } if (nullConversion.equals(NullConversion.THROW_EXCEPTION)) { Comparable rrKey = zRowKey; if (x == null) { rrKey = yRowKey; } else if (y == null) { rrKey = yRowKey; } throw new RuntimeException("There is a null value for " + "the item [" + seriesKey +", " + rrKey + ", " + colKey + "]."); } if (nullConversion != NullConversion.SKIP) { double xx = convert(x, nullConversion); double yy = convert(y, nullConversion); double zz = convert(z, nullConversion); series.add(xx, yy, zz); } } } dataset.add(series); } return dataset; } /** * Creates an {@link XYZDataset} by extracting values from specified * columns in a {@link KeyedValues3D} instance, across all the available * rows (items where any of the x, y or z values is {@code null} are * skipped). The new dataset contains a copy of the data and is completely * independent of the {@code source} dataset. *

* Note that {@link CategoryDataset3D} is an extension of * {@link KeyedValues3D} so you can use this method for any implementation * of the {@code CategoryDataset3D} interface. * * @param the series key (must implement Comparable). * @param the row key (must implement Comparable). * @param the column key (must implement Comparable). * @param source the source data ({@code null} not permitted). * @param xColKey the column key for x-values ({@code null} not permitted). * @param yColKey the column key for y-values ({@code null} not permitted). * @param zColKey the column key for z-values ({@code null} not permitted). * * @return A new dataset. * * @since 1.3 */ public static , R extends Comparable, C extends Comparable> XYZDataset extractXYZDatasetFromColumns( KeyedValues3D source, C xColKey, C yColKey, C zColKey) { return extractXYZDatasetFromColumns(source, xColKey, yColKey, zColKey, NullConversion.SKIP, null); } /** * Creates an {@link XYZDataset} by extracting values from specified * columns in a {@link KeyedValues3D} instance. The new dataset contains * a copy of the data and is completely independent of the * {@code source} dataset. Note that {@link CategoryDataset3D} is an * extension of {@link KeyedValues3D}. *

* Special handling is provided for items that contain {@code null} * values. The caller may pass in an {@code exceptions} list ( * normally empty) that will be populated with the keys of the items that * receive special handling, if any. * * @param the series key (must implement Comparable). * @param the row key (must implement Comparable). * @param the column key (must implement Comparable). * @param source the source data ({@code null} not permitted). * @param xColKey the column key for x-values ({@code null} not permitted). * @param yColKey the column key for y-values ({@code null} not permitted). * @param zColKey the column key for z-values ({@code null} not permitted). * @param nullConversion specifies the treatment for {@code null} * values in the dataset ({@code null} not permitted). * @param exceptions a list that, if not null, will be populated with * keys for the items in the source dataset that contain * {@code null} values ({@code null} permitted). * * @return A new dataset. * * @since 1.3 */ public static , R extends Comparable, C extends Comparable> XYZDataset extractXYZDatasetFromColumns( KeyedValues3D source, C xColKey, C yColKey, C zColKey, NullConversion nullConversion, List exceptions) { Args.nullNotPermitted(source, "source"); Args.nullNotPermitted(xColKey, "xColKey"); Args.nullNotPermitted(yColKey, "yColKey"); Args.nullNotPermitted(zColKey, "zColKey"); XYZSeriesCollection dataset = new XYZSeriesCollection<>(); for (S seriesKey : source.getSeriesKeys()) { XYZSeries series = new XYZSeries<>(seriesKey); for (R rowKey : source.getRowKeys()) { Number x = source.getValue(seriesKey, rowKey, xColKey); Number y = source.getValue(seriesKey, rowKey, yColKey); Number z = source.getValue(seriesKey, rowKey, zColKey); if (x != null && y != null && z != null) { series.add(x.doubleValue(), y.doubleValue(), z.doubleValue()); } else { if (exceptions != null) { // add only one key ref out of the possible 3 per item C ccKey = zColKey; if (x == null) { ccKey = xColKey; } else if (y == null) { ccKey = yColKey; } exceptions.add(new KeyedValues3DItemKey<>(seriesKey, rowKey, ccKey)); } if (nullConversion.equals(NullConversion.THROW_EXCEPTION)) { Comparable ccKey = zColKey; if (x == null) { ccKey = xColKey; } else if (y == null) { ccKey = yColKey; } throw new RuntimeException("There is a null value for " + "the item [" + seriesKey +", " + rowKey + ", " + ccKey + "]."); } if (nullConversion != NullConversion.SKIP) { double xx = convert(x, nullConversion); double yy = convert(y, nullConversion); double zz = convert(z, nullConversion); series.add(xx, yy, zz); } } } dataset.add(series); } return dataset; } /** * Returns a double primitive for the specified number, with * {@code null} values returning {@code Double.NaN} except in the * case of {@code CONVERT_TO_ZERO} which returns 0.0. Note that this * method does not throw an exception for {@code THROW_EXCEPTION}, it * expects code higher up the call chain to handle that (because there is * not enough information here to throw a useful exception). * * @param n the number ({@code null} permitted). * @param nullConversion the null conversion ({@code null} not * permitted). * * @return A double primitive. */ private static double convert(Number n, NullConversion nullConversion) { if (n != null) { return n.doubleValue(); } else { if (nullConversion.equals(NullConversion.CONVERT_TO_ZERO)) { return 0.0; } return Double.NaN; } } } orson-charts-2.1.0/src/main/java/org/jfree/chart3d/data/Dataset3D.java000066400000000000000000000054431417331271500253440ustar00rootroot00000000000000/* =========================================================== * Orson Charts : a 3D chart library for the Java(tm) platform * =========================================================== * * (C)opyright 2013-2022, by David Gilbert. All rights reserved. * * https://github.com/jfree/orson-charts * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . * * [Oracle and Java are registered trademarks of Oracle and/or its affiliates. * Other names may be trademarks of their respective owners.] * * If you do not wish to be bound by the terms of the GPL, an alternative * commercial license can be purchased. For details, please see visit the * Orson Charts home page: * * http://www.object-refinery.com/orsoncharts/index.html * */ package org.jfree.chart3d.data; import java.util.EventListener; /** * The base interface for datasets in Orson Charts. All datasets must support * the change event notification mechanism. The idea is that when a dataset * is changed, an event is passed to the plot. The plot can react to this * event, then pass on the change event to the chart. The chart in turn will * pass on the event and this can result in the chart being repainted (for * example, if the chart is displayed in a * {@link org.jfree.chart3d.Chart3DPanel}). */ public interface Dataset3D { /** * Registers a change listener to receive notification of changes to the * dataset. * * @param listener the listener ({@code null} not permitted). */ void addChangeListener(Dataset3DChangeListener listener); /** * De-registers a change listener so that it no longer receives notification * of changes to the dataset. * * @param listener the listener ({@code null} not permitted). */ void removeChangeListener(Dataset3DChangeListener listener); /** * Returns {@code true} if the specified listener is registered with * the dataset, and {@code false} otherwise. This method is used * for unit testing to confirm that listeners are removed correctly * following dataset switches. * * @param listener the listener. * * @return A boolean. */ boolean hasListener(EventListener listener); } orson-charts-2.1.0/src/main/java/org/jfree/chart3d/data/Dataset3DChangeEvent.java000066400000000000000000000052701417331271500274520ustar00rootroot00000000000000/* =========================================================== * Orson Charts : a 3D chart library for the Java(tm) platform * =========================================================== * * (C)opyright 2013-2022, by David Gilbert. All rights reserved. * * https://github.com/jfree/orson-charts * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . * * [Oracle and Java are registered trademarks of Oracle and/or its affiliates. * Other names may be trademarks of their respective owners.] * * If you do not wish to be bound by the terms of the GPL, an alternative * commercial license can be purchased. For details, please see visit the * Orson Charts home page: * * http://www.object-refinery.com/orsoncharts/index.html * */ package org.jfree.chart3d.data; import java.util.EventObject; /** * A dataset change event. Any object that implements the * {@link Dataset3DChangeListener} interface can register with a dataset to * receive notification of change events. By default, the plot classes in * Orson Charts register with their dataset to monitor dataset changes. *

* NOTE: This class is serializable, but the serialization format is subject * to change in future releases and should not be relied upon for persisting * instances of this class. */ @SuppressWarnings("serial") public class Dataset3DChangeEvent extends EventObject { private final Object dataset; /** * Creates a new dataset change event. The source can be the same as the * dataset, but this is not required. * * @param source the source. * @param dataset the dataset. */ public Dataset3DChangeEvent(Object source, Object dataset) { super(source); this.dataset = dataset; } /** * Returns the dataset that this event is associated with. This will * normally be an instance of {@link PieDataset3D}, * {@link org.jfree.chart3d.data.category.CategoryDataset3D} or * {@link org.jfree.chart3d.data.xyz.XYZDataset}. * * @return The dataset. */ public Object getDataset() { return this.dataset; } } orson-charts-2.1.0/src/main/java/org/jfree/chart3d/data/Dataset3DChangeListener.java000066400000000000000000000035421417331271500301560ustar00rootroot00000000000000/* =========================================================== * Orson Charts : a 3D chart library for the Java(tm) platform * =========================================================== * * (C)opyright 2013-2022, by David Gilbert. All rights reserved. * * https://github.com/jfree/orson-charts * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . * * [Oracle and Java are registered trademarks of Oracle and/or its affiliates. * Other names may be trademarks of their respective owners.] * * If you do not wish to be bound by the terms of the GPL, an alternative * commercial license can be purchased. For details, please see visit the * Orson Charts home page: * * http://www.object-refinery.com/orsoncharts/index.html * */ package org.jfree.chart3d.data; import java.util.EventListener; /** * The interface through which dataset change events are passed. The plot * classes implement this interface so they can receive notification of * changes to the dataset they are managing. */ public interface Dataset3DChangeListener extends EventListener { /** * Called to notify the listener that the source dataset has been * changed. * * @param event the event details. */ void datasetChanged(Dataset3DChangeEvent event); } orson-charts-2.1.0/src/main/java/org/jfree/chart3d/data/DefaultKeyedValue.java000066400000000000000000000070351417331271500271320ustar00rootroot00000000000000/* =========================================================== * Orson Charts : a 3D chart library for the Java(tm) platform * =========================================================== * * (C)opyright 2013-2022, by David Gilbert. All rights reserved. * * https://github.com/jfree/orson-charts * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . * * [Oracle and Java are registered trademarks of Oracle and/or its affiliates. * Other names may be trademarks of their respective owners.] * * If you do not wish to be bound by the terms of the GPL, an alternative * commercial license can be purchased. For details, please see visit the * Orson Charts home page: * * http://www.object-refinery.com/orsoncharts/index.html * */ package org.jfree.chart3d.data; import java.io.Serializable; import org.jfree.chart3d.internal.Args; import org.jfree.chart3d.internal.ObjectUtils; /** * A data item where a key is associated with a value (typically numerical). *

* NOTE: This class is serializable, but the serialization format is subject * to change in future releases and should not be relied upon for persisting * instances of this class. */ @SuppressWarnings("serial") public final class DefaultKeyedValue, T> implements KeyedValue, Serializable { /** The key. */ private final K key; /** The value. */ private T value; /** * Creates a new instance. * * @param key the key ({@code null} not permitted). * @param value the value. */ public DefaultKeyedValue(K key, T value) { Args.nullNotPermitted(key, "key"); this.key = key; this.value = value; } /** * Returns the key. * * @return The key (never {@code null}). */ @Override public K getKey() { return this.key; } /** * Returns the value. * * @return The value (possibly {@code null}). */ @Override public T getValue() { return this.value; } /** * Sets the value. * * @param value the value ({@code null} permitted). */ public void setValue(T value) { this.value = value; } /** * Tests this instance for equality with an arbitrary object. * * @param obj the object to test ({@code null} permitted). * * @return A boolean. */ @Override public boolean equals(Object obj) { if (obj == this) { return true; } if (!(obj instanceof DefaultKeyedValue)) { return false; } DefaultKeyedValue that = (DefaultKeyedValue) obj; if (!this.key.equals(that.key)) { return false; } if (!ObjectUtils.equals(this.value, that.value)) { return false; } return true; } @Override public String toString() { return "(" + this.key.toString() + ", " + value + ")"; } } orson-charts-2.1.0/src/main/java/org/jfree/chart3d/data/DefaultKeyedValues.java000066400000000000000000000163711417331271500273200ustar00rootroot00000000000000/* =========================================================== * Orson Charts : a 3D chart library for the Java(tm) platform * =========================================================== * * (C)opyright 2013-2022, by David Gilbert. All rights reserved. * * https://github.com/jfree/orson-charts * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . * * [Oracle and Java are registered trademarks of Oracle and/or its affiliates. * Other names may be trademarks of their respective owners.] * * If you do not wish to be bound by the terms of the GPL, an alternative * commercial license can be purchased. For details, please see visit the * Orson Charts home page: * * http://www.object-refinery.com/orsoncharts/index.html * */ package org.jfree.chart3d.data; import java.io.Serializable; import java.util.ArrayList; import java.util.List; import org.jfree.chart3d.internal.Args; /** * A list of {@code (key, value)} pairs. *

* This is the basic structure of the data required for a pie chart. *

* NOTE: This class is serializable, but the serialization format is subject * to change in future releases and should not be relied upon for persisting * instances of this class. * * @param the key type (must implement Comparable). * @param the value type. */ @SuppressWarnings("serial") public final class DefaultKeyedValues, T> implements KeyedValues, Serializable { /** Storage for the data items. */ private List> data; /** * Creates a new (empty) list of keyed values. */ public DefaultKeyedValues() { this(new ArrayList<>()); } /** * Creates a new instance with the specified keys (each associated with * a {@code null} value). There is usually no need to specify any * keys in advance, so you will normally use the default constructor. This * constructor is provided for the convenience of some internal code. * * @param keys the keys ({@code null} not permitted). */ public DefaultKeyedValues(List keys) { Args.nullNotPermitted(keys, "keys"); this.data = new ArrayList<>(); for (K key : keys) { this.data.add(new DefaultKeyedValue<>(key, null)); } } /** * Clears all the data. */ public void clear() { this.data.clear(); } /** * Adds a value or, if there is an existing value with the same key, updates * an existing value. * * @param key the key ({@code null} not permitted) * @param value the value. */ public void put(K key, T value) { Args.nullNotPermitted(key, "key"); DefaultKeyedValue dkv; int index = getIndex(key); if (index >= 0) { dkv = (DefaultKeyedValue) this.data.get(index); dkv.setValue(value); } else { this.data.add(new DefaultKeyedValue<>(key, value)); } } /** * Removes the item with the specified key, if there is one. * * @param key the key ({@code null} not permitted). */ public void remove(K key) { Args.nullNotPermitted(key, "key"); int index = getIndex(key); if (index >= 0) { remove(index); } } /** * Removes the item with the specified index. * * @param index the index. */ public void remove(int index) { this.data.remove(index); } /** * Returns the key for the item with the specified index. * * @param index the item index. * * @return The key. */ @Override public K getKey(int index) { KeyedValue kv = this.data.get(index); return kv.getKey(); } /** * Returns the index of the item with the specified key, or {@code -1} * if there is no such item. * * @param key the key ({@code null} not permitted). * * @return The item index, or {@code -1}. */ @Override public int getIndex(K key) { Args.nullNotPermitted(key, "key"); for (int i = 0; i < this.data.size(); i++) { KeyedValue kv = this.data.get(i); if (kv.getKey().equals(key)) { return i; } } return -1; } /** * Returns a list of all the keys. Note that the list will be a copy, so * modifying it will not impact this data structure. * * @return A list of keys (possibly empty, but never {@code null}). */ @Override public List getKeys() { List keys = new ArrayList<>(); for (KeyedValue kv : this.data) { keys.add(kv.getKey()); } return keys; } /** * Returns the value with the specified key. * * @param key the key ({@code null} not permitted). * * @return The value (possibly {@code null}). */ @Override public T getValue(K key) { // arg checking is performed by getIndex() int index = getIndex(key); if (index < 0) { return null; } return getValue(index); } /** * Returns the number of items in the list. * * @return The number of items in the list. */ @Override public int getItemCount() { return this.data.size(); } /** * Returns the value for the specified item. * * @param item the item index. * * @return The value (possibly {@code null}). */ @Override public T getValue(int item) { KeyedValue kv = this.data.get(item); return kv.getValue(); } /** * Returns the value for the specified item, as a double primitive, * provided that the data value is an instance of {@code Number}. * * @param item the item index. * * @return The value. */ @Override public double getDoubleValue(int item) { T n = getValue(item); if (n != null && n instanceof Number) { return ((Number) n).doubleValue(); } return Double.NaN; } /** * Tests this instance for equality with an arbitrary object. * * @param obj the object to test against ({@code null} permitted). * * @return A boolean. */ @Override public boolean equals(Object obj) { if (obj == this) { return true; } if (!(obj instanceof DefaultKeyedValues)) { return false; } DefaultKeyedValues that = (DefaultKeyedValues) obj; if (!this.data.equals(that.data)) { return false; } return true; } } orson-charts-2.1.0/src/main/java/org/jfree/chart3d/data/DefaultKeyedValues2D.java000066400000000000000000000234121417331271500275000ustar00rootroot00000000000000/* =========================================================== * Orson Charts : a 3D chart library for the Java(tm) platform * =========================================================== * * (C)opyright 2013-2022, by David Gilbert. All rights reserved. * * https://github.com/jfree/orson-charts * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . * * [Oracle and Java are registered trademarks of Oracle and/or its affiliates. * Other names may be trademarks of their respective owners.] * * If you do not wish to be bound by the terms of the GPL, an alternative * commercial license can be purchased. For details, please see visit the * Orson Charts home page: * * http://www.object-refinery.com/orsoncharts/index.html * */ package org.jfree.chart3d.data; import java.io.Serializable; import java.util.ArrayList; import java.util.List; import org.jfree.chart3d.internal.Args; /** * A two dimensional grid of (typically numerical) data that is accessible by * row and column keys. *

* NOTE: This class is serializable, but the serialization format is subject * to change in future releases and should not be relied upon for persisting * instances of this class. * * @param the row key type * @param the column key type * @param the value type. * */ @SuppressWarnings("serial") public final class DefaultKeyedValues2D, C extends Comparable, T> implements KeyedValues2D, Serializable { /** The row keys. */ List rowKeys; /** The column keys. */ List columnKeys; /** The data values. */ List> data; // one entry per row key /** * Creates a new (empty) instance. */ public DefaultKeyedValues2D() { this(new ArrayList<>(), new ArrayList<>()); } /** * Creates a new instance with the specified keys and all data values * initialized to {@code null}. * * @param rowKeys the xKeys ({@code null} not permitted). * @param columnKeys the yKeys ({@code null} not permitted). */ public DefaultKeyedValues2D(List rowKeys, List columnKeys) { Args.nullNotPermitted(rowKeys, "rowKeys"); Args.nullNotPermitted(columnKeys, "columnKeys"); this.rowKeys = new ArrayList<>(rowKeys); this.columnKeys = new ArrayList<>(columnKeys); this.data = new ArrayList<>(); for (int i = 0; i < rowKeys.size(); i++) { this.data.add(new DefaultKeyedValues<>(columnKeys)); } } /** * Returns the row key corresponding to the specified index. * * @param rowIndex the row index. * * @return The key. */ @Override public R getRowKey(int rowIndex) { return this.rowKeys.get(rowIndex); } /** * Returns the column key corresponding to the specified index. * * @param columnIndex the column index. * * @return The key. */ @Override public C getColumnKey(int columnIndex) { return this.columnKeys.get(columnIndex); } /** * Returns the index corresponding to the specified row key. * * @param rowKey the row key ({@code null} not permitted). * * @return The index. */ @Override public int getRowIndex(R rowKey) { Args.nullNotPermitted(rowKey, "rowKey"); return this.rowKeys.indexOf(rowKey); } /** * Returns the index corresponding to the specified column key. * * @param columnKey the column key ({@code null} not permitted). * * @return The index. */ @Override public int getColumnIndex(C columnKey) { Args.nullNotPermitted(columnKey, "columnKey"); return this.columnKeys.indexOf(columnKey); } /** * Returns a copy of the list of row keys. * * @return A copy of the list of row keys (never {@code null}). */ @Override public List getRowKeys() { return new ArrayList<>(this.rowKeys); } /** * Returns a copy of the list of column keys. * * @return A copy of the list of column keys (never {@code null}). */ @Override public List getColumnKeys() { return new ArrayList<>(this.columnKeys); } /** * Returns the number of row keys in the table. * * @return The number of row keys in the table. */ @Override public int getRowCount() { return this.rowKeys.size(); } /** * Returns the number of column keys in the data structure. * * @return The number of column keys. */ @Override public int getColumnCount() { return this.columnKeys.size(); } /** * Returns a value from one cell in the table. * * @param rowKey the row-key ({@code null} not permitted). * @param columnKey the column-key ({@code null} not permitted). * * @return The value (possibly {@code null}). */ @Override public T getValue(R rowKey, C columnKey) { // arg checking is handled in getXIndex() and getYIndex() int rowIndex = getRowIndex(rowKey); int columnIndex = getColumnIndex(columnKey); return getValue(rowIndex, columnIndex); } /** * Returns the value from one cell in the table. * * @param rowIndex the row index. * @param columnIndex the column index. * * @return The value (possibly {@code null}). */ @Override public T getValue(int rowIndex, int columnIndex) { return this.data.get(rowIndex).getValue(columnIndex); } /** * Returns the data item at the specified position as a double primitive. * Where the {@link #getValue(int, int)} method returns {@code null}, * this method returns {@code Double.NaN}. * * @param rowIndex the row index. * @param columnIndex the column index. * * @return The data value. */ @Override public double getDoubleValue(int rowIndex, int columnIndex) { T n = getValue(rowIndex, columnIndex); if (n != null && n instanceof Number) { return ((Number) n).doubleValue(); } return Double.NaN; } /** * Sets a value for one cell in the table. * * @param n the value ({@code null} permitted). * @param rowKey the row key ({@code null} not permitted). * @param columnKey the column key ({@code null} not permitted). */ public void setValue(T n, R rowKey, C columnKey) { Args.nullNotPermitted(rowKey, "rowKey"); Args.nullNotPermitted(columnKey, "columnKey"); if (this.data.isEmpty()) { // 1. no data - just add one new entry this.rowKeys.add(rowKey); this.columnKeys.add(columnKey); DefaultKeyedValues dkvs = new DefaultKeyedValues<>(); dkvs.put(columnKey, n); this.data.add(dkvs); } else { int rowIndex = getRowIndex(rowKey); int columnIndex = getColumnIndex(columnKey); if (rowIndex >= 0) { DefaultKeyedValues dkvs = this.data.get(rowIndex); if (columnIndex >= 0) { // 2. Both keys exist - just update the value dkvs.put(columnKey, n); } else { // 3. rowKey exists, but columnKey does not (add the // columnKey to each series) this.columnKeys.add(columnKey); for (DefaultKeyedValues kv : this.data) { kv.put(columnKey, null); } dkvs.put(columnKey, n); } } else { if (columnIndex >= 0) { // 4. rowKey does not exist, but columnKey does this.rowKeys.add(rowKey); DefaultKeyedValues d = new DefaultKeyedValues<>( this.columnKeys); d.put(columnKey, n); this.data.add(d); } else { // 5. neither key exists, need to create the new series, // plus the new entry in every series this.rowKeys.add(rowKey); this.columnKeys.add(columnKey); for (DefaultKeyedValues kv : this.data) { kv.put(columnKey, null); } DefaultKeyedValues d = new DefaultKeyedValues<>( this.columnKeys); d.put(columnKey, n); this.data.add(d); } } } } @Override public boolean equals(Object obj) { if (obj == this) { return true; } if (!(obj instanceof DefaultKeyedValues2D)) { return false; } DefaultKeyedValues2D that = (DefaultKeyedValues2D) obj; if (!this.rowKeys.equals(that.rowKeys)) { return false; } if (!this.columnKeys.equals(that.columnKeys)) { return false; } if (!this.data.equals(that.data)) { return false; } return true; } } orson-charts-2.1.0/src/main/java/org/jfree/chart3d/data/DefaultKeyedValues3D.java000066400000000000000000000252541417331271500275070ustar00rootroot00000000000000/* =========================================================== * Orson Charts : a 3D chart library for the Java(tm) platform * =========================================================== * * (C)opyright 2013-2022, by David Gilbert. All rights reserved. * * https://github.com/jfree/orson-charts * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . * * [Oracle and Java are registered trademarks of Oracle and/or its affiliates. * Other names may be trademarks of their respective owners.] * * If you do not wish to be bound by the terms of the GPL, an alternative * commercial license can be purchased. For details, please see visit the * Orson Charts home page: * * http://www.object-refinery.com/orsoncharts/index.html * */ package org.jfree.chart3d.data; import java.io.Serializable; import java.util.ArrayList; import java.util.List; import org.jfree.chart3d.internal.Args; /** * A three dimensional table of numerical values, implementing the * {@link KeyedValues3D} interface. *

* NOTE: This class is serializable, but the serialization format is subject * to change in future releases and should not be relied upon for persisting * instances of this class. * * @param the series key (must implement Comparable). * @param the row key (must implement Comparable). * @param the column key (must implement Comparable). * @param the value type. */ @SuppressWarnings("serial") public final class DefaultKeyedValues3D, R extends Comparable, C extends Comparable, V> implements KeyedValues3D, Serializable { /** The series keys. */ private final List seriesKeys; /** The row keys. */ private final List rowKeys; /** The column keys. */ private List columnKeys; /** * The data, one entry per series. Each series *must* contain the same * row and column keys. */ private List> data; // one entry per series /** * Creates a new (empty) table. */ public DefaultKeyedValues3D() { this.seriesKeys = new ArrayList<>(); this.rowKeys = new ArrayList<>(); this.columnKeys = new ArrayList<>(); this.data = new ArrayList<>(); } /** * Returns the series key with the specified index. * * @param seriesIndex the series index. * * @return The series key. */ @Override public S getSeriesKey(int seriesIndex) { return this.seriesKeys.get(seriesIndex); } /** * Returns the row key with the specified index. * * @param rowIndex the row index. * * @return The row key. */ @Override public R getRowKey(int rowIndex) { return this.rowKeys.get(rowIndex); } /** * Returns the column key with the specified index. * * @param columnIndex the column index. * * @return The column key. */ @Override public C getColumnKey(int columnIndex) { return this.columnKeys.get(columnIndex); } /** * Returns the index for the specified series key, or {@code -1} if * the key is not present in this data structure. * * @param seriesKey the series key ({@code null} not permitted). * * @return The series index or {@code -1}. */ @Override public int getSeriesIndex(S seriesKey) { Args.nullNotPermitted(seriesKey, "seriesKey"); return this.seriesKeys.indexOf(seriesKey); } /** * Returns the index for the specified row key, or {@code -1} if * the key is not present in this data structure. * * @param rowKey the row key ({@code null} not permitted). * * @return The row index or {@code -1}. */ @Override public int getRowIndex(R rowKey) { Args.nullNotPermitted(rowKey, "rowKey"); return this.rowKeys.indexOf(rowKey); } /** * Returns the index for the specified column key, or {@code -1} if * the key is not present in this data structure. * * @param columnKey the column key ({@code null} not permitted). * * @return The column index or {@code -1}. */ @Override public int getColumnIndex(C columnKey) { Args.nullNotPermitted(columnKey, "columnKey"); return this.columnKeys.indexOf(columnKey); } /** * Returns a list of the series keys for the data. Modifying this * list will have no impact on the underlying data. * * @return A list of the series keys (possibly empty, but never * {@code null}). */ @Override public List getSeriesKeys() { return new ArrayList<>(this.seriesKeys); } /** * Returns a list of the row keys for the data. Modifying this * list will have no impact on the underlying data. * * @return A list of the row keys (possibly empty, but never * {@code null}). */ @Override public List getRowKeys() { return new ArrayList<>(this.rowKeys); } /** * Returns a list of the column keys for the data. Modifying this * list will have no impact on the underlying data. * * @return A list of the column keys (possibly empty, but never * {@code null}). */ @Override public List getColumnKeys() { return new ArrayList<>(this.columnKeys); } @Override public int getSeriesCount() { return this.seriesKeys.size(); } @Override public int getRowCount() { return this.rowKeys.size(); } @Override public int getColumnCount() { return this.columnKeys.size(); } @Override public V getValue(int seriesIndex, int rowIndex, int columnIndex) { return this.data.get(seriesIndex).getValue(rowIndex, columnIndex); } /** * Returns the value for the specified data item. This method will * throw an {@code IllegalArgumentException} if the dataset does not * contain the specified keys. * * @param seriesKey the series key ({@code null} not permitted). * @param rowKey the row key ({@code null} not permitted). * @param columnKey the column key ({@code null} not permitted). * * @return The value (possibly {@code null}). */ @Override public V getValue(S seriesKey, R rowKey, C columnKey) { int seriesIndex = getSeriesIndex(seriesKey); if (seriesIndex < 0) { throw new IllegalArgumentException("Series '" + seriesKey.toString() + "' is not found."); } int rowIndex = getRowIndex(rowKey); if (rowIndex < 0) { throw new IllegalArgumentException("Row key '" + rowKey.toString() + "' is not found."); } int columnIndex = getColumnIndex(columnKey); if (columnIndex < 0) { throw new IllegalArgumentException("Column key '" + columnKey.toString() + "' is not found."); } return getValue(seriesIndex, rowIndex, columnIndex); } @Override public double getDoubleValue(int seriesIndex, int rowIndex, int columnIndex) { V n = getValue(seriesIndex, rowIndex, columnIndex); if (n != null && n instanceof Number) { return ((Number) n).doubleValue(); } return Double.NaN; } /** * Sets the value for an item in a series, overwriting any existing value. * * @param n the value ({@code null} permitted). * @param seriesKey the series key ({@code null} not permitted). * @param rowKey the row key ({@code null} not permitted). * @param columnKey the column key ({@code null} not permitted). */ public void setValue(V n, S seriesKey, R rowKey, C columnKey) { Args.nullNotPermitted(seriesKey, "seriesKey"); Args.nullNotPermitted(rowKey, "rowKey"); Args.nullNotPermitted(columnKey, "columnKey"); // cases: // 1 - the dataset is empty, so we just need to add a new layer with the // given keys; if (this.data.isEmpty()) { this.seriesKeys.add(seriesKey); this.rowKeys.add(rowKey); this.columnKeys.add(columnKey); DefaultKeyedValues2D d = new DefaultKeyedValues2D<>(); d.setValue(n, rowKey, columnKey); this.data.add(d); } int seriesIndex = getSeriesIndex(seriesKey); int rowIndex = getRowIndex(rowKey); int columnIndex = getColumnIndex(columnKey); if (rowIndex < 0) { this.rowKeys.add(rowKey); } if (columnIndex < 0) { this.columnKeys.add(columnKey); } if (rowIndex < 0 || columnIndex < 0) { for (DefaultKeyedValues2D d : this.data) { d.setValue(null, rowKey, columnKey); } } if (seriesIndex >= 0) { DefaultKeyedValues2D d = this.data.get(seriesIndex); d.setValue(n, rowKey, columnKey); } else { this.seriesKeys.add(seriesKey); DefaultKeyedValues2D d = new DefaultKeyedValues2D<>( this.rowKeys, this.columnKeys); d.setValue(n, rowKey, columnKey); this.data.add(d); } } /** * Tests this instance for equality with an arbitrary object. * * @param obj the object ({@code null} permitted). * * @return A boolean. */ @Override public boolean equals(Object obj) { if (obj == this) { return true; } if (!(obj instanceof DefaultKeyedValues3D)) { return false; } DefaultKeyedValues3D that = (DefaultKeyedValues3D) obj; if (!this.seriesKeys.equals(that.seriesKeys)) { return false; } if (!this.rowKeys.equals(that.rowKeys)) { return false; } if (!this.columnKeys.equals(that.columnKeys)) { return false; } if (!this.data.equals(that.data)) { return false; } return true; } } orson-charts-2.1.0/src/main/java/org/jfree/chart3d/data/ItemKey.java000066400000000000000000000031621417331271500251330ustar00rootroot00000000000000/* =========================================================== * Orson Charts : a 3D chart library for the Java(tm) platform * =========================================================== * * (C)opyright 2013-2022, by David Gilbert. All rights reserved. * * https://github.com/jfree/orson-charts * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . * * [Oracle and Java are registered trademarks of Oracle and/or its affiliates. * Other names may be trademarks of their respective owners.] * * If you do not wish to be bound by the terms of the GPL, an alternative * commercial license can be purchased. For details, please see visit the * Orson Charts home page: * * http://www.object-refinery.com/orsoncharts/index.html * */ package org.jfree.chart3d.data; /** * A key that references a single data item in a dataset. * * @since 1.3 */ public interface ItemKey { /** * Returns a JSON formatted string representing the key. * * @return A JSON formatted string. */ String toJSONString(); } orson-charts-2.1.0/src/main/java/org/jfree/chart3d/data/JSONUtils.java000066400000000000000000001004101417331271500253500ustar00rootroot00000000000000/* =========================================================== * Orson Charts : a 3D chart library for the Java(tm) platform * =========================================================== * * (C)opyright 2013-2022, by David Gilbert. All rights reserved. * * https://github.com/jfree/orson-charts * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . * * [Oracle and Java are registered trademarks of Oracle and/or its affiliates. * Other names may be trademarks of their respective owners.] * * If you do not wish to be bound by the terms of the GPL, an alternative * commercial license can be purchased. For details, please see visit the * Orson Charts home page: * * http://www.object-refinery.com/orsoncharts/index.html * */ package org.jfree.chart3d.data; import java.io.IOException; import java.io.StringWriter; import java.io.Writer; import java.io.Reader; import java.io.StringReader; import java.util.ArrayList; import java.util.LinkedHashMap; import java.util.List; import java.util.Map; import org.jfree.chart3d.util.json.JSONValue; import org.jfree.chart3d.util.json.parser.JSONParser; import org.jfree.chart3d.util.json.parser.ParseException; import org.jfree.chart3d.internal.Args; import org.jfree.chart3d.util.json.parser.ContainerFactory; import org.jfree.chart3d.data.category.StandardCategoryDataset3D; import org.jfree.chart3d.data.xyz.XYZDataset; import org.jfree.chart3d.data.xyz.XYZSeries; import org.jfree.chart3d.data.xyz.XYZSeriesCollection; /** * Utility methods for interchange between datasets ({@link KeyedValues}, * {@link KeyedValues3D} and {@link XYZDataset}) and JSON format strings. * * @since 1.3 */ public class JSONUtils { /** * Parses the supplied JSON string into a {@link KeyedValues} instance. *

* Implementation note: this method returns an instance of * {@link StandardPieDataset3D}). * * @param json the JSON string ({@code null} not permitted). * * @return A {@link KeyedValues} instance. */ public static KeyedValues readKeyedValues(String json) { Args.nullNotPermitted(json, "json"); StringReader in = new StringReader(json); KeyedValues result; try { result = readKeyedValues(in); } catch (IOException ex) { // not for StringReader result = null; } return result; } /** * Parses characters from the supplied reader and returns the corresponding * {@link KeyedValues} instance. *

* Implementation note: this method returns an instance of * {@link StandardPieDataset3D}). * * @param reader the reader ({@code null} not permitted). * * @return A {@code KeyedValues} instance. * * @throws IOException if there is an I/O problem. */ public static KeyedValues readKeyedValues( Reader reader) throws IOException { Args.nullNotPermitted(reader, "reader"); try { JSONParser parser = new JSONParser(); // parse with custom containers (to preserve item order) List list = (List) parser.parse(reader, createContainerFactory()); StandardPieDataset3D result = new StandardPieDataset3D<>(); for (Object item : list) { List itemAsList = (List) item; result.add(itemAsList.get(0).toString(), (Number) itemAsList.get(1)); } return result; } catch (ParseException ex) { throw new RuntimeException(ex); } } /** * Returns a string containing the data in JSON format. The format is * an array of arrays, where each sub-array represents one data value. * The sub-array should contain two items, first the item key as a string * and second the item value as a number. For example: * {@code [["Key A", 1.0], ["Key B", 2.0]]} *

* Note that this method can be used with instances of {@link PieDataset3D}. * * @param data the data ({@code null} not permitted). * * @return A string in JSON format. */ @SuppressWarnings("unchecked") public static String writeKeyedValues(KeyedValues data) { Args.nullNotPermitted(data, "data"); StringWriter sw = new StringWriter(); try { writeKeyedValues(data, sw); } catch (IOException ex) { throw new RuntimeException(ex); } return sw.toString(); } /** * Writes the data in JSON format to the supplied writer. *

* Note that this method can be used with instances of {@link PieDataset3D}. * * @param data the data ({@code null} not permitted). * @param writer the writer ({@code null} not permitted). * * @throws IOException if there is an I/O problem. */ @SuppressWarnings("unchecked") public static void writeKeyedValues(KeyedValues data, Writer writer) throws IOException { Args.nullNotPermitted(data, "data"); Args.nullNotPermitted(writer, "writer"); writer.write("["); boolean first = true; for (Object key : data.getKeys()) { if (!first) { writer.write(", "); } else { first = false; } writer.write("["); writer.write(JSONValue.toJSONString(key.toString())); writer.write(", "); writer.write(JSONValue.toJSONString(data.getValue((Comparable) key))); writer.write("]"); } writer.write("]"); } /** * Reads a data table from a JSON format string. * * @param json the string ({@code null} not permitted). * * @return A data table. */ @SuppressWarnings("unchecked") public static KeyedValues2D readKeyedValues2D(String json) { Args.nullNotPermitted(json, "json"); StringReader in = new StringReader(json); KeyedValues2D result; try { result = readKeyedValues2D(in); } catch (IOException ex) { // not for StringReader result = null; } return result; } /** * Reads a data table from a JSON format string coming from the specified * reader. * * @param reader the reader ({@code null} not permitted). * * @return A data table. * * @throws java.io.IOException if there is an I/O problem. */ @SuppressWarnings("unchecked") public static KeyedValues2D readKeyedValues2D(Reader reader) throws IOException { JSONParser parser = new JSONParser(); try { Map map = (Map) parser.parse(reader, createContainerFactory()); DefaultKeyedValues2D result = new DefaultKeyedValues2D<>(); if (map.isEmpty()) { return result; } // read the keys Object keysObj = map.get("columnKeys"); List keys = null; if (keysObj instanceof List) { keys = (List) keysObj; } else { if (keysObj == null) { throw new RuntimeException("No 'columnKeys' defined."); } else { throw new RuntimeException("Please check the 'columnKeys', " + "the format does not parse to a list."); } } Object dataObj = map.get("rows"); if (dataObj instanceof List) { List rowList = (List) dataObj; // each entry in the map has the row key and an array of // values (the length should match the list of keys above for (Object rowObj : rowList) { processRow(rowObj, keys, result); } } else { // the 'data' entry is not parsing to a list if (dataObj == null) { throw new RuntimeException("No 'rows' section defined."); } else { throw new RuntimeException("Please check the 'rows' " + "entry, the format does not parse to a list of " + "rows."); } } return result; } catch (ParseException ex) { throw new RuntimeException(ex); } } /** * Processes an entry for one row in a {@link KeyedValues2D}. * * @param rowObj the series object. * @param columnKeys the required column keys. * @param dataset the dataset. */ @SuppressWarnings("unchecked") static void processRow(Object rowObj, List columnKeys, DefaultKeyedValues2D dataset) { if (!(rowObj instanceof List)) { throw new RuntimeException("Check the 'data' section it contains " + "a row that does not parse to a list."); } // we expect the row data object to be an array containing the // rowKey and rowValueArray entries, where rowValueArray // should have the same number of entries as the columnKeys List rowList = (List) rowObj; Object rowKey = rowList.get(0); Object rowDataObj = rowList.get(1); if (!(rowDataObj instanceof List)) { throw new RuntimeException("Please check the row entry for " + rowKey + " because it is not parsing to a list (of " + "rowKey and rowDataValues items."); } List rowData = (List) rowDataObj; if (rowData.size() != columnKeys.size()) { throw new RuntimeException("The values list for series " + rowKey + " does not contain the correct number of " + "entries to match the columnKeys."); } for (int c = 0; c < rowData.size(); c++) { Object columnKey = columnKeys.get(c); dataset.setValue(objToDouble(rowData.get(c)), rowKey.toString(), columnKey.toString()); } } /** * Writes a data table to a string in JSON format. * * @param data the data ({@code null} not permitted). * * @return The string. */ public static String writeKeyedValues2D(KeyedValues2D data) { Args.nullNotPermitted(data, "data"); StringWriter sw = new StringWriter(); try { writeKeyedValues2D(data, sw); } catch (IOException ex) { throw new RuntimeException(ex); } return sw.toString(); } /** * Writes the data in JSON format to the supplied writer. * * @param data the data ({@code null} not permitted). * @param writer the writer ({@code null} not permitted). * * @throws IOException if there is an I/O problem. */ @SuppressWarnings("unchecked") public static void writeKeyedValues2D(KeyedValues2D data, Writer writer) throws IOException { Args.nullNotPermitted(data, "data"); Args.nullNotPermitted(writer, "writer"); List columnKeys = data.getColumnKeys(); List rowKeys = data.getRowKeys(); writer.write("{"); if (!columnKeys.isEmpty()) { writer.write("\"columnKeys\": ["); boolean first = true; for (Comparable columnKey : columnKeys) { if (!first) { writer.write(", "); } else { first = false; } writer.write(JSONValue.toJSONString(columnKey.toString())); } writer.write("]"); } if (!rowKeys.isEmpty()) { writer.write(", \"rows\": ["); boolean firstRow = true; for (Comparable rowKey : rowKeys) { if (!firstRow) { writer.write(", ["); } else { writer.write("["); firstRow = false; } // write the row data writer.write(JSONValue.toJSONString(rowKey.toString())); writer.write(", ["); boolean first = true; for (Comparable columnKey : columnKeys) { if (!first) { writer.write(", "); } else { first = false; } writer.write(JSONValue.toJSONString(data.getValue(rowKey, columnKey))); } writer.write("]]"); } writer.write("]"); } writer.write("}"); } /** * Parses the supplied string and (if possible) creates a * {@link KeyedValues3D} instance. * * @param json the JSON string ({@code null} not permitted). * * @return A {@code KeyedValues3D} instance. */ public static KeyedValues3D readKeyedValues3D(String json) { StringReader in = new StringReader(json); KeyedValues3D result; try { result = readKeyedValues3D(in); } catch (IOException ex) { // not for StringReader result = null; } return result; } /** * Parses character data from the reader and (if possible) creates a * {@link KeyedValues3D} instance. This method will read back the data * written by {@link JSONUtils#writeKeyedValues3D( * org.jfree.chart3d.data.KeyedValues3D, java.io.Writer) }. * * @param reader the reader ({@code null} not permitted). * * @return A {@code KeyedValues3D} instance. * * @throws IOException if there is an I/O problem. */ @SuppressWarnings("unchecked") public static KeyedValues3D readKeyedValues3D(Reader reader) throws IOException { JSONParser parser = new JSONParser(); try { Map map = (Map) parser.parse(reader, createContainerFactory()); StandardCategoryDataset3D result = new StandardCategoryDataset3D(); if (map.isEmpty()) { return result; } // read the row keys, we'll use these to validate the row keys // supplied with the data Object rowKeysObj = map.get("rowKeys"); List rowKeys; if (rowKeysObj instanceof List) { rowKeys = (List) rowKeysObj; } else { if (rowKeysObj == null) { throw new RuntimeException("No 'rowKeys' defined."); } else { throw new RuntimeException("Please check the 'rowKeys', " + "the format does not parse to a list."); } } // read the column keys, the data is provided later in rows that // should have the same number of entries as the columnKeys list Object columnKeysObj = map.get("columnKeys"); List columnKeys; if (columnKeysObj instanceof List) { columnKeys = (List) columnKeysObj; } else { if (columnKeysObj == null) { throw new RuntimeException("No 'columnKeys' defined."); } else { throw new RuntimeException("Please check the 'columnKeys', " + "the format does not parse to a list."); } } // the data object should be a list of data series Object dataObj = map.get("data"); if (dataObj instanceof List) { List seriesList = (List) dataObj; // each entry in the map has the series name as the key, and // the value is a map of row data (rowKey, list of values) for (Object seriesObj : seriesList) { processSeries(seriesObj, rowKeys, columnKeys, result); } } else { // the 'data' entry is not parsing to a list if (dataObj == null) { throw new RuntimeException("No 'data' section defined."); } else { throw new RuntimeException("Please check the 'data' " + "entry, the format does not parse to a list of " + "series."); } } return result; } catch (ParseException ex) { throw new RuntimeException(ex); } } /** * Processes an entry for one series. * * @param seriesObj the series object. * @param rowKeys the expected row keys. * @param columnKeys the required column keys. */ static , C extends Comparable> void processSeries(Object seriesObj, List rowKeys, List columnKeys, StandardCategoryDataset3D dataset) { if (!(seriesObj instanceof Map)) { throw new RuntimeException("Check the 'data' section it contains " + "a series that does not parse to a map."); } // we expect the series data object to be a map of // rowKey ==> rowValueArray entries, where rowValueArray // should have the same number of entries as the columnKeys Map seriesMap = (Map) seriesObj; Object seriesKey = seriesMap.get("seriesKey"); Object seriesRowsObj = seriesMap.get("rows"); if (!(seriesRowsObj instanceof Map)) { throw new RuntimeException("Please check the series entry for " + seriesKey + " because it is not parsing to a map (of " + "rowKey -> rowDataValues items."); } Map seriesData = (Map) seriesRowsObj; for (Object rowKey : seriesData.keySet()) { if (!rowKeys.contains(rowKey)) { throw new RuntimeException("The row key " + rowKey + " is not " + "listed in the rowKeys entry."); } Object rowValuesObj = seriesData.get(rowKey); if (!(rowValuesObj instanceof List)) { throw new RuntimeException("Please check the entry for series " + seriesKey + " and row " + rowKey + " because it " + "does not parse to a list of values."); } List rowValues = (List) rowValuesObj; if (rowValues.size() != columnKeys.size()) { throw new RuntimeException("The values list for series " + seriesKey + " and row " + rowKey + " does not " + "contain the correct number of entries to match " + "the columnKeys."); } for (int c = 0; c < rowValues.size(); c++) { Object columnKey = columnKeys.get(c); dataset.addValue(objToDouble(rowValues.get(c)), seriesKey.toString(), rowKey.toString(), columnKey.toString()); } } } /** * Returns a string containing the data in JSON format. * * @param dataset the data ({@code null} not permitted). * * @return A string in JSON format. */ public static String writeKeyedValues3D(KeyedValues3D dataset) { Args.nullNotPermitted(dataset, "dataset"); StringWriter sw = new StringWriter(); try { writeKeyedValues3D(dataset, sw); } catch (IOException ex) { throw new RuntimeException(ex); } return sw.toString(); } /** * Writes the dataset in JSON format to the supplied writer. * * @param dataset the dataset ({@code null} not permitted). * @param writer the writer ({@code null} not permitted). * * @throws IOException if there is an I/O problem. */ @SuppressWarnings("unchecked") public static void writeKeyedValues3D(KeyedValues3D dataset, Writer writer) throws IOException { Args.nullNotPermitted(dataset, "dataset"); Args.nullNotPermitted(writer, "writer"); writer.write("{"); if (!dataset.getColumnKeys().isEmpty()) { writer.write("\"columnKeys\": ["); boolean first = true; for (Object key : dataset.getColumnKeys()) { if (!first) { writer.write(", "); } else { first = false; } writer.write(JSONValue.toJSONString(key.toString())); } writer.write("], "); } // write the row keys if (!dataset.getRowKeys().isEmpty()) { writer.write("\"rowKeys\": ["); boolean first = true; for (Object key : dataset.getRowKeys()) { if (!first) { writer.write(", "); } else { first = false; } writer.write(JSONValue.toJSONString(key.toString())); } writer.write("], "); } // write the data which is zero, one or many data series // a data series has a 'key' and a 'rows' attribute // the 'rows' attribute is a Map from 'rowKey' -> array of data values if (dataset.getSeriesCount() != 0) { writer.write("\"series\": ["); boolean first = true; for (Object seriesKey : dataset.getSeriesKeys()) { if (!first) { writer.write(", "); } else { first = false; } writer.write("{\"seriesKey\": "); writer.write(JSONValue.toJSONString(seriesKey.toString())); writer.write(", \"rows\": ["); boolean firstRow = true; for (Object rowKey : dataset.getRowKeys()) { if (countForRowInSeries(dataset, (Comparable) seriesKey, (Comparable) rowKey) > 0) { if (!firstRow) { writer.write(", ["); } else { writer.write("["); firstRow = false; } // write the row values writer.write(JSONValue.toJSONString(rowKey.toString()) + ", ["); for (int c = 0; c < dataset.getColumnCount(); c++) { Object columnKey = dataset.getColumnKey(c); if (c != 0) { writer.write(", "); } writer.write(JSONValue.toJSONString( dataset.getValue((Comparable) seriesKey, (Comparable) rowKey, (Comparable) columnKey))); } writer.write("]]"); } } writer.write("]}"); } writer.write("]"); } writer.write("}"); } /** * Returns the number of non-{@code null} entries for the specified * series and row. * * @param data the dataset ({@code null} not permitted). * @param seriesKey the series key ({@code null} not permitted). * @param rowKey the row key ({@code null} not permitted). * * @return The count. */ @SuppressWarnings("unchecked") private static int countForRowInSeries(KeyedValues3D data, Comparable seriesKey, Comparable rowKey) { Args.nullNotPermitted(data, "data"); Args.nullNotPermitted(seriesKey, "seriesKey"); Args.nullNotPermitted(rowKey, "rowKey"); int seriesIndex = data.getSeriesIndex(seriesKey); if (seriesIndex < 0) { throw new IllegalArgumentException("Series not found: " + seriesKey); } int rowIndex = data.getRowIndex(rowKey); if (rowIndex < 0) { throw new IllegalArgumentException("Row not found: " + rowKey); } int count = 0; for (int c = 0; c < data.getColumnCount(); c++) { Object n = data.getValue(seriesIndex, rowIndex, c); if (n != null) { count++; } } return count; } /** * Parses the string and (if possible) creates an {XYZDataset} instance * that represents the data. This method will read back the data that * is written by * {@link #writeXYZDataset(org.jfree.chart3d.data.xyz.XYZDataset)}. * * @param json a JSON formatted string ({@code null} not permitted). * * @return A dataset. * * @see #writeXYZDataset(org.jfree.chart3d.data.xyz.XYZDataset) */ public static XYZDataset readXYZDataset(String json) { Args.nullNotPermitted(json, "json"); StringReader in = new StringReader(json); XYZDataset result; try { result = readXYZDataset(in); } catch (IOException ex) { // not for StringReader result = null; } return result; } /** * Parses character data from the reader and (if possible) creates an * {XYZDataset} instance that represents the data. * * @param reader a reader ({@code null} not permitted). * * @return A dataset. * * @throws IOException if there is an I/O problem. */ @SuppressWarnings("unchecked") public static XYZDataset readXYZDataset(Reader reader) throws IOException { JSONParser parser = new JSONParser(); XYZSeriesCollection result = new XYZSeriesCollection<>(); try { List list = (List) parser.parse(reader, createContainerFactory()); // each entry in the array should be a series array (where the // first item is the series name and the next value is an array // (of arrays of length 3) containing the data items for (Object seriesArray : list) { if (seriesArray instanceof List) { List seriesList = (List) seriesArray; XYZSeries series = createSeries(seriesList); result.add(series); } else { throw new RuntimeException( "Input for a series did not parse to a list."); } } } catch (ParseException ex) { throw new RuntimeException(ex); } return result; } /** * Returns a string containing the dataset in JSON format. * * @param dataset the dataset ({@code null} not permitted). * * @return A string in JSON format. */ public static String writeXYZDataset(XYZDataset dataset) { StringWriter sw = new StringWriter(); try { writeXYZDataset(dataset, sw); } catch (IOException ex) { throw new RuntimeException(ex); } return sw.toString(); } /** * Writes the dataset in JSON format to the supplied writer. * * @param dataset the data ({@code null} not permitted). * @param writer the writer ({@code null} not permitted). * * @throws IOException if there is an I/O problem. */ @SuppressWarnings("unchecked") public static void writeXYZDataset(XYZDataset dataset, Writer writer) throws IOException { writer.write("["); boolean first = true; for (Object seriesKey : dataset.getSeriesKeys()) { if (!first) { writer.write(", ["); } else { writer.write("["); first = false; } writer.write(JSONValue.toJSONString(seriesKey.toString())); writer.write(", ["); int seriesIndex = dataset.getSeriesIndex((Comparable) seriesKey); int itemCount = dataset.getItemCount(seriesIndex); for (int i = 0; i < itemCount; i++) { if (i != 0) { writer.write(", "); } writer.write("["); writer.write(JSONValue.toJSONString( dataset.getX(seriesIndex, i))); writer.write(", "); writer.write(JSONValue.toJSONString( dataset.getY(seriesIndex, i))); writer.write(", "); writer.write(JSONValue.toJSONString( dataset.getZ(seriesIndex, i))); writer.write("]"); } writer.write("]]"); } writer.write("]"); } /** * Converts an arbitrary object to a double. * * @param obj an object ({@code null} permitted). * * @return A double primitive (possibly Double.NaN). */ private static double objToDouble(Object obj) { if (obj == null) { return Double.NaN; } if (obj instanceof Number) { return ((Number) obj).doubleValue(); } double result = Double.NaN; try { result = Double.parseDouble(obj.toString()); } catch (Exception e) { } return result; } /** * Creates an {@link XYZSeries} from the supplied list. The list is * coming from the JSON parser and should contain the series name as the * first item, and a list of data items as the second item. The list of * data items should be a list of lists ( * * @param sArray the series array. * * @return A data series. */ @SuppressWarnings("unchecked") private static XYZSeries createSeries(List sArray) { Comparable key = (Comparable) sArray.get(0); List dataItems = (List) sArray.get(1); XYZSeries series = new XYZSeries(key); for (Object item : dataItems) { if (item instanceof List) { List xyz = (List) item; if (xyz.size() != 3) { throw new RuntimeException( "A data item should contain three numbers, " + "but we have " + xyz); } double x = objToDouble(xyz.get(0)); double y = objToDouble(xyz.get(1)); double z = objToDouble(xyz.get(2)); series.add(x, y, z); } else { throw new RuntimeException( "Expecting a data item (x, y, z) for series " + key + " but found " + item + "."); } } return series; } /** * Returns a custom container factory for the JSON parser. We create this * so that the collections respect the order of elements. * * @return The container factory. */ private static ContainerFactory createContainerFactory() { return new ContainerFactory() { @Override public Map createObjectContainer() { return new LinkedHashMap(); } @Override public List creatArrayContainer() { return new ArrayList(); } }; } } orson-charts-2.1.0/src/main/java/org/jfree/chart3d/data/KeyedValue.java000066400000000000000000000036061417331271500256250ustar00rootroot00000000000000/* =========================================================== * Orson Charts : a 3D chart library for the Java(tm) platform * =========================================================== * * (C)opyright 2013-2022, by David Gilbert. All rights reserved. * * https://github.com/jfree/orson-charts * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . * * [Oracle and Java are registered trademarks of Oracle and/or its affiliates. * Other names may be trademarks of their respective owners.] * * If you do not wish to be bound by the terms of the GPL, an alternative * commercial license can be purchased. For details, please see visit the * Orson Charts home page: * * http://www.object-refinery.com/orsoncharts/index.html * */ package org.jfree.chart3d.data; /** * A {@code (key, value)} pair that is used as a building block for some * data structures for the charts. * * @param The key type. * @param The value type. */ public interface KeyedValue, T> { /** * Returns the key (by design, this key is required to be * non-{@code null}). * * @return The key (never {@code null}). */ K getKey(); /** * Returns the value. * * @return The value (possibly {@code null}). */ T getValue(); } orson-charts-2.1.0/src/main/java/org/jfree/chart3d/data/KeyedValues.java000066400000000000000000000050531417331271500260060ustar00rootroot00000000000000/* =========================================================== * Orson Charts : a 3D chart library for the Java(tm) platform * =========================================================== * * (C)opyright 2013-2022, by David Gilbert. All rights reserved. * * https://github.com/jfree/orson-charts * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . * * [Oracle and Java are registered trademarks of Oracle and/or its affiliates. * Other names may be trademarks of their respective owners.] * * If you do not wish to be bound by the terms of the GPL, an alternative * commercial license can be purchased. For details, please see visit the * Orson Charts home page: * * http://www.object-refinery.com/orsoncharts/index.html * */ package org.jfree.chart3d.data; import java.util.List; /** * A list of values that are associated with unique keys. * * @param the key type (must implement Comparable). * @param the value type. */ public interface KeyedValues, T> extends Values { /** * Returns the key for the specified item in the list. * * @param index the item index. * * @return The key. */ K getKey(int index); /** * Returns the index for the specified key, or {@code -1} if the key * is not present in the list. * * @param key the key ({@code null} not permitted). * * @return The item index, or {@code -1}. */ int getIndex(K key); /** * Returns a list of all the keys. Note that the list will be a copy, so * modifying it will not impact this data structure. * * @return A list of keys (possibly empty, but never {@code null}). */ List getKeys(); /** * Returns the value associated with the specified key, or * {@code null}. * * @param key the key ({@code null} not permitted). * * @return The value (possibly {@code null}). */ T getValue(K key); } orson-charts-2.1.0/src/main/java/org/jfree/chart3d/data/KeyedValues2D.java000066400000000000000000000077671417331271500262120ustar00rootroot00000000000000/* =========================================================== * Orson Charts : a 3D chart library for the Java(tm) platform * =========================================================== * * (C)opyright 2013-2022, by David Gilbert. All rights reserved. * * https://github.com/jfree/orson-charts * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . * * [Oracle and Java are registered trademarks of Oracle and/or its affiliates. * Other names may be trademarks of their respective owners.] * * If you do not wish to be bound by the terms of the GPL, an alternative * commercial license can be purchased. For details, please see visit the * Orson Charts home page: * * http://www.object-refinery.com/orsoncharts/index.html * */ package org.jfree.chart3d.data; import java.util.List; /** * A two dimensional grid of data values where each value is uniquely * identified by two keys (the {@code rowKey} and the * {@code columnKey}). Any instance of {@code Comparable} can be * used as a key ({@code String} objects are instances of * {@code Comparable}, making them convenient key objects). * * @param The row key type. * @param The column key type. * @param The value type. */ public interface KeyedValues2D, C extends Comparable, T> extends Values2D { /** * Returns the row key with the specified index. * * @param rowIndex the row index. * * @return The key. */ R getRowKey(int rowIndex); /** * Returns the column key with the specified index. * * @param columnIndex the index. * * @return The key. */ C getColumnKey(int columnIndex); /** * Returns the index of the specified key, or {@code -1} if there * is no such key. * * @param rowKey the row key ({@code null} not permitted). * * @return The index, or {@code -1}. */ int getRowIndex(R rowKey); /** * Returns the index of the specified key, or {@code -1} if there * is no such key. * * @param columnKey the column key ({@code null} not permitted). * * @return The index, or {@code -1}. */ int getColumnIndex(C columnKey); /** * Returns a list of the row keys (the order is significant, since data * values can be accessed by index as well as by key). *

* NOTE: this method must be implemented so that modifications to the * returned list do not impact the underlying data structure. * * @return A list of row keys. */ List getRowKeys(); /** * Returns a list of the column keys (the order is significant, since data * values can be accessed by index as well as by key). *

* NOTE: this method must be implemented so that modifications to the * returned list do not impact the underlying data structure. * * @return A list of column keys. */ List getColumnKeys(); /** * Returns the value (possibly {@code null}) associated with the * specified keys. If either or both of the keys is not defined in this * data structure, a runtime exception will be thrown. * * @param rowKey the row key ({@code null} not permitted). * @param columnKey the column key ({@code null} not permitted). * * @return The value (possibly {@code null}). */ T getValue(R rowKey, C columnKey); } orson-charts-2.1.0/src/main/java/org/jfree/chart3d/data/KeyedValues3D.java000066400000000000000000000107201417331271500261720ustar00rootroot00000000000000/* =========================================================== * Orson Charts : a 3D chart library for the Java(tm) platform * =========================================================== * * (C)opyright 2013-2022, by David Gilbert. All rights reserved. * * https://github.com/jfree/orson-charts * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . * * [Oracle and Java are registered trademarks of Oracle and/or its affiliates. * Other names may be trademarks of their respective owners.] * * If you do not wish to be bound by the terms of the GPL, an alternative * commercial license can be purchased. For details, please see visit the * Orson Charts home page: * * http://www.object-refinery.com/orsoncharts/index.html * */ package org.jfree.chart3d.data; import java.util.List; /** * A three dimensional cube of data values where each value is uniquely * identified by three keys (the {@code seriesKey}, {@code rowKey} * and {@code columnKey}). * * @param The series key type. * @param The row key type. * @param The column key type. * @param The value type. */ public interface KeyedValues3D, R extends Comparable, C extends Comparable, T> extends Values3D { /** * Returns a list of the series keys for the dataset. Modifying this * list will have no impact on the underlying dataset. * * @return A list of the series keys (possibly empty, but never * {@code null}). */ List getSeriesKeys(); /** * Returns a list of the row keys for the dataset. Modifying this * list will have no impact on the underlying dataset. * * @return A list of the row keys (possibly empty, but never * {@code null}). */ List getRowKeys(); /** * Returns a list of the column keys for the dataset. Modifying this * list will have no impact on the underlying dataset. * * @return A list of the column keys (possibly empty, but never * {@code null}). */ List getColumnKeys(); /** * Returns the series key with the specified index. * * @param seriesIndex the series index. * * @return The key. */ S getSeriesKey(int seriesIndex); /** * Returns the row key with the specified index. * * @param rowIndex the row index. * * @return The key. */ R getRowKey(int rowIndex); /** * Returns the column key with the specified index. * * @param columnIndex the column index. * * @return The key. */ C getColumnKey(int columnIndex); /** * Returns the index of the specified series key, or {@code -1} if * there is no matching key. * * @param serieskey the series key ({@code null} not permitted). * * @return The key index, or {@code -1}. */ int getSeriesIndex(S serieskey); /** * Returns the index of the specified row key, or {@code -1} if there * is no matching key. * * @param rowkey the row key ({@code null} not permitted). * * @return The row index or {@code -1}. */ int getRowIndex(R rowkey); /** * Returns the index of the specified column key, or {@code -1} if * there is no matching key. * * @param columnkey the column key ({@code null} not permitted). * * @return The column index or {@code -1}. */ int getColumnIndex(C columnkey); /** * Returns the value for a given series, row and column. * * @param seriesKey the series key ({@code null} not permitted). * @param rowKey the row key ({@code null} not permitted). * @param columnKey the column key ({@code null} not permitted). * * @return The value (possibly {@code null}). */ T getValue(S seriesKey, R rowKey, C columnKey); } orson-charts-2.1.0/src/main/java/org/jfree/chart3d/data/KeyedValues3DItemKey.java000066400000000000000000000120071417331271500274620ustar00rootroot00000000000000/* =========================================================== * Orson Charts : a 3D chart library for the Java(tm) platform * =========================================================== * * (C)opyright 2013-2022, by David Gilbert. All rights reserved. * * https://github.com/jfree/orson-charts * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . * * [Oracle and Java are registered trademarks of Oracle and/or its affiliates. * Other names may be trademarks of their respective owners.] * * If you do not wish to be bound by the terms of the GPL, an alternative * commercial license can be purchased. For details, please see visit the * Orson Charts home page: * * http://www.object-refinery.com/orsoncharts/index.html * */ package org.jfree.chart3d.data; import java.io.Serializable; import org.jfree.chart3d.internal.Args; import org.jfree.chart3d.internal.ObjectUtils; /** * An object that references one data item in a {@link KeyedValues3D} data * structure. Instances of this class are immutable (subject to the caller * using series, row and column keys that are immutable). * * @since 1.3 */ public class KeyedValues3DItemKey, R extends Comparable, C extends Comparable> implements ItemKey, Comparable>, Serializable { /** The series key. */ S seriesKey; /** The row key. */ R rowKey; /** The column key. */ C columnKey; /** * Creates a new instance. * * @param seriesKey the series key ({@code null} not permitted). * @param rowKey the row key ({@code null} not permitted). * @param columnKey the column key ({@code null} not permitted). */ public KeyedValues3DItemKey(S seriesKey, R rowKey, C columnKey) { Args.nullNotPermitted(seriesKey, "seriesKey"); Args.nullNotPermitted(rowKey, "rowKey"); Args.nullNotPermitted(columnKey, "columnKey"); this.seriesKey = seriesKey; this.rowKey = rowKey; this.columnKey = columnKey; } /** * Returns the series key. * * @return The series key (never {@code null}). */ public S getSeriesKey() { return this.seriesKey; } /** * Returns the row key. * * @return The row key (never {@code null}). */ public R getRowKey() { return this.rowKey; } /** * Returns the column key. * * @return The column key (never {@code null}). */ public C getColumnKey() { return this.columnKey; } @Override public int compareTo(KeyedValues3DItemKey key) { int result = this.seriesKey.compareTo(key.getSeriesKey()); if (result == 0) { result = this.rowKey.compareTo(key.rowKey); if (result == 0) { result = this.columnKey.compareTo(key.columnKey); } } return result; } /** * Tests this key for equality with an arbitrary object. * * @param obj the object ({@code null} permitted). * * @return A boolean. */ @Override public boolean equals(Object obj) { if (obj == this) { return true; } if (!(obj instanceof KeyedValues3DItemKey)) { return false; } KeyedValues3DItemKey that = (KeyedValues3DItemKey) obj; if (!this.seriesKey.equals(that.seriesKey)) { return false; } if (!this.rowKey.equals(that.rowKey)) { return false; } if (!this.columnKey.equals(that.columnKey)) { return false; } return true; } @Override public int hashCode() { int hash = 3; hash = 17 * hash + ObjectUtils.hashCode(this.seriesKey); hash = 17 * hash + ObjectUtils.hashCode(this.rowKey); hash = 17 * hash + ObjectUtils.hashCode(this.columnKey); return hash; } @Override public String toJSONString() { return "{\"seriesKey\": \"" + this.seriesKey.toString() + "\", " + "\"rowKey\": \"" + this.rowKey.toString() + "\", " + "\"columnKey\": \"" + this.columnKey.toString() + "\"}"; } @Override public String toString() { return "Values3DItemKey[series=" + seriesKey.toString() + ",row=" + rowKey.toString() + ",column=" + columnKey.toString() + "]"; } } orson-charts-2.1.0/src/main/java/org/jfree/chart3d/data/KeyedValues3DItemKeys.java000066400000000000000000000126731417331271500276560ustar00rootroot00000000000000/* =========================================================== * Orson Charts : a 3D chart library for the Java(tm) platform * =========================================================== * * (C)opyright 2013-2022, by David Gilbert. All rights reserved. * * https://github.com/jfree/orson-charts * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . * * [Oracle and Java are registered trademarks of Oracle and/or its affiliates. * Other names may be trademarks of their respective owners.] * * If you do not wish to be bound by the terms of the GPL, an alternative * commercial license can be purchased. For details, please see visit the * Orson Charts home page: * * http://www.object-refinery.com/orsoncharts/index.html * */ package org.jfree.chart3d.data; import java.util.ArrayList; import java.util.Collection; import org.jfree.chart3d.internal.Args; /** * Utility methods related to the {@link KeyedValues3DItemKey} class. * * @since 1.3 */ public class KeyedValues3DItemKeys { private KeyedValues3DItemKeys() { // no need to instantiate this } /** * Returns a collection containing all the item keys for the specified * series. * * @param data the data ({@code null} not permitted). * @param seriesKey the series key ({@code null} not permitted). * * @param the series key type * @param the row key type * @param the column key type * @param the value type * * @return A collection of item keys (never {@code null}). */ public static , R extends Comparable, C extends Comparable, T> Collection itemKeysForSeries( KeyedValues3D data, S seriesKey) { Args.nullNotPermitted(data, "data"); Args.nullNotPermitted(seriesKey, "seriesKey"); Collection result = new ArrayList<>(); if (!data.getSeriesKeys().contains(seriesKey)) { return result; } for (R rowKey: data.getRowKeys()) { for (C columnKey: data.getColumnKeys()) { KeyedValues3DItemKey key = new KeyedValues3DItemKey<>( seriesKey, rowKey, columnKey); result.add(key); } } return result; } /** * Returns a collection containing all the item keys for the specified * row. * * @param the series key type * @param the row key type * @param the column key type * @param the value type * * @param data the data ({@code null} not permitted). * @param rowKey the row key ({@code null} not permitted). * * @return A collection of item keys (never {@code null}). */ public static , R extends Comparable, C extends Comparable, T> Collection itemKeysForRow(KeyedValues3D data, R rowKey) { Args.nullNotPermitted(data, "data"); Args.nullNotPermitted(rowKey, "rowKey"); Collection result = new ArrayList<>(); if (!data.getRowKeys().contains(rowKey)) { return result; } for (S seriesKey: data.getSeriesKeys()) { for (C columnKey: data.getColumnKeys()) { KeyedValues3DItemKey key = new KeyedValues3DItemKey<>(seriesKey, rowKey, columnKey); result.add(key); } } return result; } /** * Returns a collection containing all the item keys for the specified * column. * * @param the series key type * @param the row key type * @param the column key type. * @param the value type. * * @param data the data ({@code null} not permitted). * @param columnKey the column key ({@code null} not permitted). * * @return A collection of item keys (never {@code null}). */ public static , R extends Comparable, C extends Comparable, T> Collection itemKeysForColumn( KeyedValues3D data, C columnKey) { Args.nullNotPermitted(data, "data"); Args.nullNotPermitted(columnKey, "columnKey"); Collection result = new ArrayList<>(); if (!data.getColumnKeys().contains(columnKey)) { return result; } for (S seriesKey: data.getSeriesKeys()) { for (R rowKey: data.getRowKeys()) { KeyedValues3DItemKey key = new KeyedValues3DItemKey<>( seriesKey, rowKey, columnKey); result.add(key); } } return result; } } orson-charts-2.1.0/src/main/java/org/jfree/chart3d/data/KeyedValuesItemKey.java000066400000000000000000000055561417331271500273060ustar00rootroot00000000000000/* =========================================================== * Orson Charts : a 3D chart library for the Java(tm) platform * =========================================================== * * (C)opyright 2013-2022, by David Gilbert. All rights reserved. * * https://github.com/jfree/orson-charts * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . * * [Oracle and Java are registered trademarks of Oracle and/or its affiliates. * Other names may be trademarks of their respective owners.] * * If you do not wish to be bound by the terms of the GPL, an alternative * commercial license can be purchased. For details, please see visit the * Orson Charts home page: * * http://www.object-refinery.com/orsoncharts/index.html * */ package org.jfree.chart3d.data; import java.io.Serializable; import org.jfree.chart3d.internal.Args; /** * An object that references one data item in a {@link KeyedValues3D} data * structure. * * @since 1.3 */ public class KeyedValuesItemKey implements ItemKey, Serializable { /** The key for the item. */ Comparable key; /** * Creates a new instance. * * @param key the key ({@code null} not permitted). */ public KeyedValuesItemKey(Comparable key) { Args.nullNotPermitted(key, "key"); this.key = key; } /** * Returns the key. * * @return The key (never {@code null}). */ public Comparable getKey() { return this.key; } /** * Tests this instance for equality with an arbitrary object. * * @param obj the object ({@code null} not permitted). * * @return A boolean. */ @Override public boolean equals(Object obj) { if (obj == this) { return true; } if (!(obj instanceof KeyedValuesItemKey)) { return false; } KeyedValuesItemKey that = (KeyedValuesItemKey) obj; if (!this.key.equals(that.key)) { return false; } return true; } @Override public String toJSONString() { return "{\"key\": \"" + this.key.toString() + "\"}"; } @Override public String toString() { return "ValuesItemKey[" + this.key.toString() + "]"; } }orson-charts-2.1.0/src/main/java/org/jfree/chart3d/data/NullConversion.java000066400000000000000000000035161417331271500265470ustar00rootroot00000000000000/* =========================================================== * Orson Charts : a 3D chart library for the Java(tm) platform * =========================================================== * * (C)opyright 2013-2022, by David Gilbert. All rights reserved. * * https://github.com/jfree/orson-charts * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . * * [Oracle and Java are registered trademarks of Oracle and/or its affiliates. * Other names may be trademarks of their respective owners.] * * If you do not wish to be bound by the terms of the GPL, an alternative * commercial license can be purchased. For details, please see visit the * Orson Charts home page: * * http://www.object-refinery.com/orsoncharts/index.html * */ package org.jfree.chart3d.data; /** * Options for handling {@code null} values during dataset extraction * (SKIP, CONVERT_TO_NAN, CONVERT_TO_ZERO, THROW_EXCEPTION). * * @since 1.3 */ public enum NullConversion { /** Skip the item that contains the {@code null} value. */ SKIP, /** Convert the {@code null} to {@code Double.NaN}. */ CONVERT_TO_NAN, /** Convert the {@code null} to zero. */ CONVERT_TO_ZERO, /** Throw a runtime exception. */ THROW_EXCEPTION } orson-charts-2.1.0/src/main/java/org/jfree/chart3d/data/PieDataset3D.java000066400000000000000000000035671417331271500260070ustar00rootroot00000000000000/* =========================================================== * Orson Charts : a 3D chart library for the Java(tm) platform * =========================================================== * * (C)opyright 2013-2022, by David Gilbert. All rights reserved. * * https://github.com/jfree/orson-charts * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . * * [Oracle and Java are registered trademarks of Oracle and/or its affiliates. * Other names may be trademarks of their respective owners.] * * If you do not wish to be bound by the terms of the GPL, an alternative * commercial license can be purchased. For details, please see visit the * Orson Charts home page: * * http://www.object-refinery.com/orsoncharts/index.html * */ package org.jfree.chart3d.data; import org.jfree.chart3d.plot.PiePlot3D; /** * The interface through which the {@link PiePlot3D} class obtains data for * pie charts. The interface defines methods for reading data only, not for * updating the data (however, classes that implement the interface will * typically provide their own methods for updating the dataset). * * @param The key type (must implement Comparable) */ public interface PieDataset3D> extends KeyedValues, Values, Dataset3D { } orson-charts-2.1.0/src/main/java/org/jfree/chart3d/data/Range.java000066400000000000000000000154461417331271500246300ustar00rootroot00000000000000/* =========================================================== * Orson Charts : a 3D chart library for the Java(tm) platform * =========================================================== * * (C)opyright 2013-2022, by David Gilbert. All rights reserved. * * https://github.com/jfree/orson-charts * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . * * [Oracle and Java are registered trademarks of Oracle and/or its affiliates. * Other names may be trademarks of their respective owners.] * * If you do not wish to be bound by the terms of the GPL, an alternative * commercial license can be purchased. For details, please see visit the * Orson Charts home page: * * http://www.object-refinery.com/orsoncharts/index.html * */ package org.jfree.chart3d.data; import java.io.Serializable; import org.jfree.chart3d.internal.Args; /** * Represents a range of data values (instances are immutable). *

* NOTE: This class is serializable, but the serialization format is subject * to change in future releases and should not be relied upon for persisting * instances of this class. */ @SuppressWarnings("serial") public class Range implements Serializable { /** The lower bound of the range. */ private double min; /** The upper bound of the range. */ private double max; /** * Creates a new range instance. * * @param min the lower bound of the range. * @param max the upper bound of the range. */ public Range(double min, double max) { if (min > max) { throw new IllegalArgumentException("Requires min <= max."); } this.min = min; this.max = max; } /** * Returns the lower bound of the range. * * @return The lower bound of the range. */ public double getMin() { return this.min; } /** * Returns the upper bound of the range. * * @return The upper bound of the range. */ public double getMax() { return this.max; } /** * Returns the length of the range. * * @return The length of the range. */ public double getLength() { return this.max - this.min; } /** * Returns {@code true} if the range includes the specified value, * and {@code false} otherwise. * * @param value the value. * * @return A boolean. */ public boolean contains(double value) { return value >= this.min && value <= this.max; } /** * Returns either (a) the supplied value, if it falls within the range, or * (b) the range minimum or maximum value, whichever is closest to value. * * @param value the value. * * @return The pegged value. */ public double peggedValue(double value) { return Math.max(this.min, Math.min(this.max, value)); } /** * Returns {@code true} if the range intersects the interval defined * by the two bounds (the order of the bounds is not important), and * {@code false} otherwise. * * @param bound1 the first boundary value. * @param bound2 the second boundary value. * * @return A boolean. */ public boolean intersects(double bound1, double bound2) { double lowerBound = Math.min(bound1, bound2); double upperBound = Math.max(bound1, bound2); if (upperBound < this.min) { return false; } if (lowerBound > this.max) { return false; } return true; } /** * Returns {@code true} if this range intersects with * the specified range, and {@code false} otherwise. * * @param range the range ({@code null} not permitted). * * @return A boolean. * * @since 1.2 */ public boolean intersects(Range range) { Args.nullNotPermitted(range, "range"); return intersects(range.getMin(), range.getMax()); } /** * Returns the value as a percentage along the range. * * @param value the value. * * @return The percentage. */ public double percent(double value) { return (value - this.min) / getLength(); } /** * Returns the value as a percentage along the range, with optionally the * result inverted (that is, p becomes 1.0 - p). * * @param value the value. * @param inverted invert the result? * * @return The percentage. * * @since 1.5 */ public double percent(double value, boolean inverted) { double p = percent(value); if (inverted) { p = 1.0 - p; } return p; } /** * Returns the value corresponding to the specified percentage. * * @param percent the percentage along the range. * * @return The value. * * @since 1.1 */ public double value(double percent) { return this.min + percent * (this.max - this.min); } /** * Tests this instance for equality with an arbitrary object. * * @param obj the object ({@code null} permitted). * * @return A boolean. */ @Override public boolean equals(Object obj) { if (obj == this) { return true; } if (!(obj instanceof Range)) { return false; } Range that = (Range) obj; if (this.min != that.min) { return false; } if (this.max != that.max) { return false; } return true; } /** * Returns a hash code for this instance. * * @return A hash code. */ @Override public int hashCode() { int hash = 7; hash = 43 * hash + (int) (Double.doubleToLongBits(this.min) ^ (Double.doubleToLongBits(this.min) >>> 32)); hash = 43 * hash + (int) (Double.doubleToLongBits(this.max) ^ (Double.doubleToLongBits(this.max) >>> 32)); return hash; } /** * Returns a string representation of this instance, primarily for * debugging purposes. * * @return A string. */ @Override public String toString() { return "Range[" + this.min + ", " + this.max + "]"; } } orson-charts-2.1.0/src/main/java/org/jfree/chart3d/data/Series3DChangeEvent.java000066400000000000000000000035351417331271500273210ustar00rootroot00000000000000/* =========================================================== * Orson Charts : a 3D chart library for the Java(tm) platform * =========================================================== * * (C)opyright 2013-2022, by David Gilbert. All rights reserved. * * https://github.com/jfree/orson-charts * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . * * [Oracle and Java are registered trademarks of Oracle and/or its affiliates. * Other names may be trademarks of their respective owners.] * * If you do not wish to be bound by the terms of the GPL, an alternative * commercial license can be purchased. For details, please see visit the * Orson Charts home page: * * http://www.object-refinery.com/orsoncharts/index.html * */ package org.jfree.chart3d.data; import java.io.Serializable; import java.util.EventObject; /** * An event that signals a change to a series (the "3D" in the name is to * differentiate this class from the similar event object in JFreeChart). * * @since 1.6 */ public class Series3DChangeEvent extends EventObject implements Serializable{ /** * Constructs a new event. * * @param source the source of the change event. */ public Series3DChangeEvent(Object source) { super(source); } } orson-charts-2.1.0/src/main/java/org/jfree/chart3d/data/Series3DChangeListener.java000066400000000000000000000033411417331271500300200ustar00rootroot00000000000000/* =========================================================== * Orson Charts : a 3D chart library for the Java(tm) platform * =========================================================== * * (C)opyright 2013-2022, by David Gilbert. All rights reserved. * * https://github.com/jfree/orson-charts * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . * * [Oracle and Java are registered trademarks of Oracle and/or its affiliates. * Other names may be trademarks of their respective owners.] * * If you do not wish to be bound by the terms of the GPL, an alternative * commercial license can be purchased. For details, please see visit the * Orson Charts home page: * * http://www.object-refinery.com/orsoncharts/index.html * */ package org.jfree.chart3d.data; import java.util.EventListener; /** * Methods for receiving notification of changes to a data series. * * @since 1.6 */ public interface Series3DChangeListener extends EventListener { /** * Called when an observed series changes in some way. * * @param event information about the change. */ void seriesChanged(Series3DChangeEvent event); } orson-charts-2.1.0/src/main/java/org/jfree/chart3d/data/StandardPieDataset3D.java000066400000000000000000000154311417331271500274610ustar00rootroot00000000000000/* =========================================================== * Orson Charts : a 3D chart library for the Java(tm) platform * =========================================================== * * (C)opyright 2013-2022, by David Gilbert. All rights reserved. * * https://github.com/jfree/orson-charts * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . * * [Oracle and Java are registered trademarks of Oracle and/or its affiliates. * Other names may be trademarks of their respective owners.] * * If you do not wish to be bound by the terms of the GPL, an alternative * commercial license can be purchased. For details, please see visit the * Orson Charts home page: * * http://www.object-refinery.com/orsoncharts/index.html * */ package org.jfree.chart3d.data; import java.io.Serializable; import java.util.List; import org.jfree.chart3d.internal.Args; import org.jfree.chart3d.plot.PiePlot3D; /** * A dataset that can be used with a {@link PiePlot3D}. This class represents * an ordered list of (key, value) items. The keys can be any instance of * {@link Comparable} ({@code String} is commonly used) and the values * can be any {@link Number} instance (bearing in mind that the downstream * code will use the {@code toDouble()} method to read values) or * {@code null}. *

* This class provides an implementation of * {@code KeyedValues<Number>}, so the following useful utility * methods can be used: *
    * {@link DataUtils#total(org.jfree.chart3d.data.Values)} * {@link JSONUtils#writeKeyedValues(org.jfree.chart3d.data.KeyedValues)} *
*

* NOTE: This class is serializable, but the serialization format is subject * to change in future releases and should not be relied upon for persisting * instances of this class. * * @param the key type. */ @SuppressWarnings("serial") public final class StandardPieDataset3D> extends AbstractDataset3D implements PieDataset3D, Serializable { /** Storage for the data. */ private DefaultKeyedValues data; /** * Creates a new (empty) dataset. */ public StandardPieDataset3D() { this.data = new DefaultKeyedValues<>(); } /** * Returns the number of items in the dataset. * * @return The number of items in the dataset. */ @Override public int getItemCount() { return this.data.getItemCount(); } /** * Returns the key for the specified item in the list. * * @param item the item index. * * @return The key. */ @Override public K getKey(int item) { return this.data.getKey(item); } /** * Returns the index for the specified key, or {@code -1} if the key * is not present in the list. * * @param key the key ({@code null} not permitted). * * @return The item index, or {@code -1}. */ @Override public int getIndex(K key) { return this.data.getIndex(key); } /** * Returns the value for the specified item. * * @param item the item index. * * @return The value for the specified item (possibly {@code null}). */ @Override public Number getValue(int item) { return this.data.getValue(item); } /** * Returns the value associated with the specified key, or * {@code null}. * * @param key the key ({@code null} not permitted). * * @return The value (possibly {@code null}). */ @Override public Number getValue(K key) { return this.data.getValue(key); } /** * Adds a value to the dataset (if there is already a value with the given * key, the value is overwritten) and sends a {@link Dataset3DChangeEvent} * to all registered listeners. * * @param key the key ({@code null} not permitted). * @param value the value. */ public void add(K key, double value) { add(key, Double.valueOf(value)); } /** * Adds a value to the dataset (if there is already a value with the given * key, the value is overwritten) and sends a {@link Dataset3DChangeEvent} * to all registered listeners. * * @param key the key ({@code null} not permitted). * @param value the value ({@code null} permitted). */ public void add(K key, Number value) { Args.nullNotPermitted(key, "key"); this.data.put(key, value); fireDatasetChanged(); } /** * Returns a list of all the keys in the dataset. Note that the list will * be a copy, so modifying it will not impact this dataset. * * @return A list of keys (possibly empty, but never {@code null}). */ @Override public List getKeys() { return this.data.getKeys(); } /** * Returns the value for the specified item as a double primitive. Where * the {@link #getValue(int)} method returns {@code null}, this method * returns {@code Double.NaN}. * * @param item the item index. * * @return The value for the specified item. */ @Override public double getDoubleValue(int item) { return this.data.getDoubleValue(item); } /** * Tests this dataset for equality with an arbitrary object. * * @param obj the object ({@code null} not permitted). * * @return A boolean. */ @Override public boolean equals(Object obj) { if (obj == this) { return true; } if (!(obj instanceof StandardPieDataset3D)) { return false; } StandardPieDataset3D that = (StandardPieDataset3D) obj; if (!this.data.equals(that.data)) { return false; } return true; } /** * Returns a string representation of this instance, primarily for * debugging purposes. *

* Implementation note: the current implementation (which is subject to * change) writes the dataset in JSON format using * {@link JSONUtils#writeKeyedValues(org.jfree.chart3d.data.KeyedValues)}. * * @return A string. */ @Override public String toString() { return JSONUtils.writeKeyedValues(this); } } orson-charts-2.1.0/src/main/java/org/jfree/chart3d/data/Values.java000066400000000000000000000044061417331271500250250ustar00rootroot00000000000000/* =========================================================== * Orson Charts : a 3D chart library for the Java(tm) platform * =========================================================== * * (C)opyright 2013-2022, by David Gilbert. All rights reserved. * * https://github.com/jfree/orson-charts * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . * * [Oracle and Java are registered trademarks of Oracle and/or its affiliates. * Other names may be trademarks of their respective owners.] * * If you do not wish to be bound by the terms of the GPL, an alternative * commercial license can be purchased. For details, please see visit the * Orson Charts home page: * * http://www.object-refinery.com/orsoncharts/index.html * */ package org.jfree.chart3d.data; /** * A generic representation of a one dimensional list of data values. * * @param The value type. */ public interface Values { /** * Returns the number of items in the dataset. * * @return The number of items in the dataset. */ int getItemCount(); /** * Returns the value for the specified item. * * @param item the item index. * * @return The value for the specified item (possibly {@code null}). */ T getValue(int item); /** * Returns the value for the specified item as a double primitive, provided * that the data type is a subclass of {@code Number}. Where * the {@link #getValue(int)} method returns {@code null}, this method * returns {@code Double.NaN}. * * @param item the item index. * * @return The value for the specified item. */ double getDoubleValue(int item); } orson-charts-2.1.0/src/main/java/org/jfree/chart3d/data/Values2D.java000066400000000000000000000050721417331271500252130ustar00rootroot00000000000000/* =========================================================== * Orson Charts : a 3D chart library for the Java(tm) platform * =========================================================== * * (C)opyright 2013-2022, by David Gilbert. All rights reserved. * * https://github.com/jfree/orson-charts * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . * * [Oracle and Java are registered trademarks of Oracle and/or its affiliates. * Other names may be trademarks of their respective owners.] * * If you do not wish to be bound by the terms of the GPL, an alternative * commercial license can be purchased. For details, please see visit the * Orson Charts home page: * * http://www.object-refinery.com/orsoncharts/index.html * */ package org.jfree.chart3d.data; /** * A generic representation of a two dimensional grid of data values. * * @param the type of value stored in the grid. */ public interface Values2D { /** * Returns the number of rows in the grid. * * @return The number of rows in the grid. */ int getRowCount(); /** * Returns the number of columns in the grid. * * @return The number of columns in the grid. */ int getColumnCount(); /** * Returns the data item at the specified position. * * @param rowIndex the row index. * @param columnIndex the column index. * * @return The data value (possibly {@code null}). */ T getValue(int rowIndex, int columnIndex); /** * Returns the data value at the specified position as a double primitive, * or {@code Double.NaN} if the value is not an instance of * {@code Number}. Where the {@link #getValue(int, int)} method * returns {@code null}, this method returns {@code Double.NaN}. * * @param rowIndex the row index. * @param columnIndex the column index. * * @return The data value. */ double getDoubleValue(int rowIndex, int columnIndex); } orson-charts-2.1.0/src/main/java/org/jfree/chart3d/data/Values3D.java000066400000000000000000000061051417331271500252120ustar00rootroot00000000000000/* =========================================================== * Orson Charts : a 3D chart library for the Java(tm) platform * =========================================================== * * (C)opyright 2013-2022, by David Gilbert. All rights reserved. * * https://github.com/jfree/orson-charts * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . * * [Oracle and Java are registered trademarks of Oracle and/or its affiliates. * Other names may be trademarks of their respective owners.] * * If you do not wish to be bound by the terms of the GPL, an alternative * commercial license can be purchased. For details, please see visit the * Orson Charts home page: * * http://www.object-refinery.com/orsoncharts/index.html * */ package org.jfree.chart3d.data; /** * A generic representation of a three dimensional grid (cube) of data values. * We refer to the indices in the three dimensions as the * {@code seriesIndex}, the {@code rowIndex} and the * {@code columnIndex} (to match the downstream use of this data * structure to represent data values in a three dimensional plot). * * @param The value type (normally a numeric type). * * @see KeyedValues3D */ public interface Values3D { /** * Returns the number of items in the x-dimension. * * @return The number of items in the x-dimension. */ int getSeriesCount(); /** * Returns the number of items in the y-dimension. * * @return The number of items in the y-dimension. */ int getRowCount(); /** * Returns the number of items in the z-dimension. * * @return The number of items in the z-dimension. */ int getColumnCount(); /** * Returns the data item at the specified position. * * @param seriesIndex the series-index. * @param rowIndex the row-index. * @param columnIndex the column-index. * * @return The data value (possibly {@code null}). */ T getValue(int seriesIndex, int rowIndex, int columnIndex); /** * Returns the data item at the specified position as a double primitive. * Where the {@link #getValue(int, int, int) } method returns * {@code null}, this method returns {@code Double.NaN}. * * @param seriesIndex the series index. * @param rowIndex the row index. * @param columnIndex the column index. * * @return The data value. */ double getDoubleValue(int seriesIndex, int rowIndex, int columnIndex); } orson-charts-2.1.0/src/main/java/org/jfree/chart3d/data/category/000077500000000000000000000000001417331271500245345ustar00rootroot00000000000000orson-charts-2.1.0/src/main/java/org/jfree/chart3d/data/category/CategoryDataset3D.java000066400000000000000000000040671417331271500306600ustar00rootroot00000000000000/* =========================================================== * Orson Charts : a 3D chart library for the Java(tm) platform * =========================================================== * * (C)opyright 2013-2022, by David Gilbert. All rights reserved. * * https://github.com/jfree/orson-charts * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . * * [Oracle and Java are registered trademarks of Oracle and/or its affiliates. * Other names may be trademarks of their respective owners.] * * If you do not wish to be bound by the terms of the GPL, an alternative * commercial license can be purchased. For details, please see visit the * Orson Charts home page: * * http://www.object-refinery.com/orsoncharts/index.html * */ package org.jfree.chart3d.data.category; import org.jfree.chart3d.data.Dataset3D; import org.jfree.chart3d.data.KeyedValues3D; import org.jfree.chart3d.plot.CategoryPlot3D; /** * An interface for a dataset with multiple series of data in the form of * {@code (rowKey, columnKey, value)}. This is the standard data * interface used by the {@link CategoryPlot3D} class. * * @param the series key type (must implement Comparable) * @param the row key type (must implement Comparable) * @param the column key type (must implement Comparable) */ public interface CategoryDataset3D, R extends Comparable, C extends Comparable> extends KeyedValues3D, Dataset3D { } orson-charts-2.1.0/src/main/java/org/jfree/chart3d/data/category/StandardCategoryDataset3D.java000066400000000000000000000257161417331271500323450ustar00rootroot00000000000000/* =========================================================== * Orson Charts : a 3D chart library for the Java(tm) platform * =========================================================== * * (C)opyright 2013-2022, by David Gilbert. All rights reserved. * * https://github.com/jfree/orson-charts * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . * * [Oracle and Java are registered trademarks of Oracle and/or its affiliates. * Other names may be trademarks of their respective owners.] * * If you do not wish to be bound by the terms of the GPL, an alternative * commercial license can be purchased. For details, please see visit the * Orson Charts home page: * * http://www.object-refinery.com/orsoncharts/index.html * */ package org.jfree.chart3d.data.category; import java.util.List; import java.io.Serializable; import org.jfree.chart3d.data.AbstractDataset3D; import org.jfree.chart3d.data.DefaultKeyedValues3D; import org.jfree.chart3d.data.JSONUtils; import org.jfree.chart3d.data.KeyedValues; import org.jfree.chart3d.internal.Args; /** * A standard implementation of the {@link CategoryDataset3D} interface. * This dataset is typically used to create bar charts and stacked bar charts. *

* NOTE: This class is serializable, but the serialization format is subject * to change in future releases and should not be relied upon for persisting * instances of this class. */ @SuppressWarnings("serial") public final class StandardCategoryDataset3D , R extends Comparable, C extends Comparable> extends AbstractDataset3D implements CategoryDataset3D, Serializable { /** * Storage for the data. */ private final DefaultKeyedValues3D data; /** * Creates a new (empty) dataset. */ public StandardCategoryDataset3D() { this.data = new DefaultKeyedValues3D<>(); } /** * Returns the number of data series in the dataset. * * @return The number of data series. */ @Override public int getSeriesCount() { return this.data.getSeriesCount(); } /** * Returns the number of rows in the dataset. * * @return The number of rows. */ @Override public int getRowCount() { return this.data.getRowCount(); } /** * Returns the number of columns in the dataset. * * @return The number of columns. */ @Override public int getColumnCount() { return this.data.getColumnCount(); } /** * Returns the key for the specified series. * * @param seriesIndex the series index. * * @return The series key. */ @Override public S getSeriesKey(int seriesIndex) { return this.data.getSeriesKey(seriesIndex); } /** * Returns the key for the specified row. * * @param rowIndex The row index. * * @return The row key. */ @Override public R getRowKey(int rowIndex) { return this.data.getRowKey(rowIndex); } /** * Returns the key for the specified column. * * @param columnIndex the column index. * * @return The column key. */ @Override public C getColumnKey(int columnIndex) { return this.data.getColumnKey(columnIndex); } /** * Returns the index for the specified series key, or {@code -1} if the * key is not defined in the dataset. * * @param serieskey the series key ({@code null} not permitted). * * @return The series index or {@code -1}. */ @Override public int getSeriesIndex(S serieskey) { return this.data.getSeriesIndex(serieskey); } /** * Returns the index of the specified row key, or {@code -1} if there * is no matching key. * * @param rowkey the row key ({@code null} not permitted). * * @return The row index or {@code -1}. */ @Override public int getRowIndex(R rowkey) { // arg checking is covered return this.data.getRowIndex(rowkey); } /** * Returns the index of the specified column key, or {@code -1} if * there is no matching key. * * @param columnkey the column key ({@code null} not permitted). * * @return The column index or {@code -1}. */ @Override public int getColumnIndex(C columnkey) { // arg checking is covered return this.data.getColumnIndex(columnkey); } /** * Returns a list of the series keys for the dataset. Modifying this * list will have no impact on the underlying dataset. * * @return A list of the series keys (possibly empty, but never * {@code null}). */ @Override public List getSeriesKeys() { return this.data.getSeriesKeys(); } /** * Returns a list of the row keys for the dataset. Modifying this * list will have no impact on the underlying dataset. * * @return A list of the row keys (possibly empty, but never * {@code null}). */ @Override public List getRowKeys() { return this.data.getRowKeys(); } /** * Returns a list of the column keys for the dataset. Modifying this * list will have no impact on the underlying dataset. * * @return A list of the column keys (possibly empty, but never * {@code null}). */ @Override public List getColumnKeys() { return this.data.getColumnKeys(); } /** * Returns the value for a series at the specified cell (referenced by * row key and column key). * * @param seriesKey the series key ({@code null} not permitted). * @param rowKey the row key ({@code null} not permitted). * @param columnKey the column key ({@code null} not permitted). * * @return The value (possibly {@code null}). */ @Override public Number getValue(S seriesKey, R rowKey, C columnKey) { return this.data.getValue(seriesKey, rowKey, columnKey); } /** * Returns the value for a series at the specified cell (referenced by * row index and column index). * * @param seriesIndex the series index. * @param rowIndex the row index. * @param columnIndex the column index. * * @return The value (possibly {@code null}). */ @Override public Number getValue(int seriesIndex, int rowIndex, int columnIndex) { return this.data.getValue(seriesIndex, rowIndex, columnIndex); } /** * Sets the value for a series at the specified cell (referenced by row * key and column key). * * @param n the value ({@code null} permitted). * @param seriesKey the series key ({@code null} not permitted). * @param rowKey the row key ({@code null} not permitted). * @param columnKey the column key ({@code null} not permitted). */ public void setValue(Number n, S seriesKey, R rowKey, C columnKey) { this.data.setValue(n, seriesKey, rowKey, columnKey); fireDatasetChanged(); } /** * Adds a value for a series at the specified cell (referenced by row key * and column key). This method simply calls {@link #setValue( * java.lang.Number, java.lang.Comparable, java.lang.Comparable, * java.lang.Comparable) }. * * @param n the value ({@code null} permitted). * @param seriesKey the series key ({@code null} not permitted). * @param rowKey the row key ({@code null} not permitted). * @param columnKey the column key ({@code null} not permitted). */ public void addValue(Number n, S seriesKey, R rowKey, C columnKey) { setValue(n, seriesKey, rowKey, columnKey); } /** * Returns the value for a series at the specified cell (referenced by row * index and column index) as a double primitive. If the stored data * value is {@code null}, this method returns {@code Double.NaN}. * * @param seriesIndex the series index. * @param rowIndex the row index. * @param columnIndex the column index. * * @return The value (possibly {@code Double.NaN}). */ @Override public double getDoubleValue(int seriesIndex, int rowIndex, int columnIndex) { return this.data.getDoubleValue(seriesIndex, rowIndex, columnIndex); } /** * Adds a data series as a single row in the dataset. * * @param seriesKey the series key ({@code null} not permitted). * @param data the data ({@code null} not permitted). */ @SuppressWarnings("unchecked") public void addSeriesAsRow(S seriesKey, KeyedValues data) { addSeriesAsRow(seriesKey, (R) seriesKey, data); } /** * Adds a data series as a single row in the dataset. * * @param seriesKey the series key ({@code null} not permitted). * @param rowKey the row key ({@code null} not permitted). * @param data the data ({@code null} not permitted). */ public void addSeriesAsRow(S seriesKey, R rowKey, KeyedValues data) { Args.nullNotPermitted(seriesKey, "seriesKey"); Args.nullNotPermitted(data, "data"); for (C key : data.getKeys()) { setValue(data.getValue(key), seriesKey, rowKey, key); } } /** * Tests this instance for equality with an arbitrary object. * * @param obj the object to test against ({@code null} permitted). * * @return A boolean. */ @Override public boolean equals(Object obj) { if (obj == this) { return true; } if (!(obj instanceof StandardCategoryDataset3D)) { return false; } StandardCategoryDataset3D that = (StandardCategoryDataset3D) obj; if (!this.data.equals(that.data)) { return false; } return true; } /** * Returns a string representation of this instance, primarily for * debugging purposes. *

* Implementation note: the current implementation (which is subject to * change) writes the dataset in JSON format using * {@link JSONUtils#writeKeyedValues3D(org.jfree.chart3d.data.KeyedValues3D)}. * * @return A string. */ @Override public String toString() { return JSONUtils.writeKeyedValues3D(this); } } orson-charts-2.1.0/src/main/java/org/jfree/chart3d/data/category/package-info.java000066400000000000000000000002151417331271500277210ustar00rootroot00000000000000/** * Datasets that can be used by the {@link org.jfree.chart3d.plot.CategoryPlot3D} * class. */ package org.jfree.chart3d.data.category;orson-charts-2.1.0/src/main/java/org/jfree/chart3d/data/function/000077500000000000000000000000001417331271500245445ustar00rootroot00000000000000orson-charts-2.1.0/src/main/java/org/jfree/chart3d/data/function/Function3D.java000066400000000000000000000042111417331271500273610ustar00rootroot00000000000000/* =========================================================== * Orson Charts : a 3D chart library for the Java(tm) platform * =========================================================== * * (C)opyright 2013-2022, by David Gilbert. All rights reserved. * * https://github.com/jfree/orson-charts * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . * * [Oracle and Java are registered trademarks of Oracle and/or its affiliates. * Other names may be trademarks of their respective owners.] * * If you do not wish to be bound by the terms of the GPL, an alternative * commercial license can be purchased. For details, please see visit the * Orson Charts home page: * * http://www.object-refinery.com/orsoncharts/index.html * */ package org.jfree.chart3d.data.function; import java.io.Serializable; import org.jfree.chart3d.data.Range; import org.jfree.chart3d.data.xyz.XYZDatasetUtils; /** * Represents a function {@code y = f(x, z)}. *

* A dataset can be created by sampling a function - see the * {@link XYZDatasetUtils#sampleFunction(Function3D, String, Range, double, Range, double)} * method. In addition, any {@code Function3D} instance can be plotted * by a {@link org.jfree.chart3d.renderer.xyz.SurfaceRenderer}. */ public interface Function3D extends Serializable { /** * Returns the value of the function ('y') for the specified inputs ('x' * and 'z'). * * @param x the x-value. * @param z the z-value. * * @return The function value. */ double getValue(double x, double z); } orson-charts-2.1.0/src/main/java/org/jfree/chart3d/data/function/Function3DUtils.java000066400000000000000000000064551417331271500304160ustar00rootroot00000000000000/* =========================================================== * Orson Charts : a 3D chart library for the Java(tm) platform * =========================================================== * * (C)opyright 2013-2022, by David Gilbert. All rights reserved. * * https://github.com/jfree/orson-charts * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . * * [Oracle and Java are registered trademarks of Oracle and/or its affiliates. * Other names may be trademarks of their respective owners.] * * If you do not wish to be bound by the terms of the GPL, an alternative * commercial license can be purchased. For details, please see visit the * Orson Charts home page: * * http://www.object-refinery.com/orsoncharts/index.html * */ package org.jfree.chart3d.data.function; import org.jfree.chart3d.data.Range; import org.jfree.chart3d.internal.Args; /** * Utility methods related to {@link Function3D}. * * @since 1.1 */ public class Function3DUtils { private Function3DUtils() { // no need to instantiate this } /** * Returns the range of y-values in the function by sampling. * * @param f the function ({@code null} not permitted). * @param xRange the x-range to sample ({@code null} not permitted). * @param zRange the z-range to sample ({@code null} not permitted). * @param xSamples the number of x-samples (must be at least 2). * @param zSamples the number of z-samples (must be at least 2). * @param ignoreNaN if {@code true}, any {@code NaN} values will * be ignored. * * @return The range ({@code null} in the case that the function * returns no valid values). */ public static Range findYRange(Function3D f, Range xRange, Range zRange, int xSamples, int zSamples, boolean ignoreNaN) { Args.nullNotPermitted(f, "f"); Args.nullNotPermitted(xRange, "xRange"); Args.nullNotPermitted(zRange, "zRange"); double min = Double.POSITIVE_INFINITY; double max = Double.NEGATIVE_INFINITY; for (int xIndex = 0; xIndex <= xSamples - 1; xIndex++) { double fracX = xIndex / (xSamples - 1.0); double x = xRange.value(fracX); for (int zIndex = 0; zIndex <= zSamples - 1; zIndex++) { double fracZ = zIndex / (zSamples - 1.0); double z = zRange.value(fracZ); double y = f.getValue(x, z); if (Double.isNaN(y) && ignoreNaN) { continue; } min = Math.min(y, min); max = Math.max(y, max); } } if (min <= max) { return new Range(min, max); } return null; } } orson-charts-2.1.0/src/main/java/org/jfree/chart3d/data/function/package-info.java000066400000000000000000000001611417331271500277310ustar00rootroot00000000000000/** * Representation of functions in the form {@code y = f(x, z)}. */ package org.jfree.chart3d.data.function; orson-charts-2.1.0/src/main/java/org/jfree/chart3d/data/package-info.java000066400000000000000000000003671417331271500261140ustar00rootroot00000000000000/** * Core data structures used as the building blocks for datasets in Orson * Charts. The {@link org.jfree.chart3d.data.DataUtils} class provides important * static utility methods for working with data. */ package org.jfree.chart3d.data; orson-charts-2.1.0/src/main/java/org/jfree/chart3d/data/xyz/000077500000000000000000000000001417331271500235515ustar00rootroot00000000000000orson-charts-2.1.0/src/main/java/org/jfree/chart3d/data/xyz/XYZDataItem.java000066400000000000000000000073471417331271500265320ustar00rootroot00000000000000/* =========================================================== * Orson Charts : a 3D chart library for the Java(tm) platform * =========================================================== * * (C)opyright 2013-2022, by David Gilbert. All rights reserved. * * https://github.com/jfree/orson-charts * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . * * [Oracle and Java are registered trademarks of Oracle and/or its affiliates. * Other names may be trademarks of their respective owners.] * * If you do not wish to be bound by the terms of the GPL, an alternative * commercial license can be purchased. For details, please see visit the * Orson Charts home page: * * http://www.object-refinery.com/orsoncharts/index.html * */ package org.jfree.chart3d.data.xyz; import java.io.Serializable; /** * Represents a single {@code (x, y, z)} data item, which can be added to * a {@link XYZSeries}. Instances of this class are immutable. *

* NOTE: This class is serializable, but the serialization format is subject * to change in future releases and should not be relied upon for persisting * instances of this class. */ @SuppressWarnings("serial") public class XYZDataItem implements Serializable { /** The x-value. */ private final double x; /** The y-value. */ private final double y; /** The z-value. */ private final double z; /** * Creates a new (immutable) instance. * * @param x the x-value. * @param y the y-value. * @param z the z-value. */ public XYZDataItem(double x, double y, double z) { this.x = x; this.y = y; this.z = z; } /** * Returns the x-value. * * @return The x-value. */ public double getX() { return x; } /** * Returns the y-value. * * @return The y-value. */ public double getY() { return y; } /** * Returns the z-value. * * @return The z-value. */ public double getZ() { return z; } /** * Tests this instance for equality with an arbitrary object. * * @param obj the object ({@code null} permitted). * * @return A boolean. */ @Override public boolean equals(Object obj) { if (obj == this) { return true; } if (!(obj instanceof XYZDataItem)) { return false; } XYZDataItem that = (XYZDataItem) obj; if (this.x != that.x) { return false; } if (this.y != that.y) { return false; } if (this.z != that.z) { return false; } return true; } @Override public int hashCode() { int hash = 5; hash = 79 * hash + (int) (Double.doubleToLongBits(this.x) ^ (Double.doubleToLongBits(this.x) >>> 32)); hash = 79 * hash + (int) (Double.doubleToLongBits(this.y) ^ (Double.doubleToLongBits(this.y) >>> 32)); hash = 79 * hash + (int) (Double.doubleToLongBits(this.z) ^ (Double.doubleToLongBits(this.z) >>> 32)); return hash; } } orson-charts-2.1.0/src/main/java/org/jfree/chart3d/data/xyz/XYZDataset.java000066400000000000000000000071051417331271500264170ustar00rootroot00000000000000/* =========================================================== * Orson Charts : a 3D chart library for the Java(tm) platform * =========================================================== * * (C)opyright 2013-2022, by David Gilbert. All rights reserved. * * https://github.com/jfree/orson-charts * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . * * [Oracle and Java are registered trademarks of Oracle and/or its affiliates. * Other names may be trademarks of their respective owners.] * * If you do not wish to be bound by the terms of the GPL, an alternative * commercial license can be purchased. For details, please see visit the * Orson Charts home page: * * http://www.object-refinery.com/orsoncharts/index.html * */ package org.jfree.chart3d.data.xyz; import java.util.List; import org.jfree.chart3d.data.Dataset3D; import org.jfree.chart3d.plot.XYZPlot; /** * Defines the methods used to access data in the form of multiple series * containing {@code (x, y, z)} data items. This is the standard * dataset format used by the {@link XYZPlot} class. * * @param The series key type (which must implement Comparable). */ public interface XYZDataset> extends Dataset3D { /** * Returns the number of series in the dataset. * * @return The number of series in the dataset. */ int getSeriesCount(); /** * Returns a list of the series-keys for the dataset. Modifying this * list will have no impact on the underlying dataset. * * @return A list of the series-keys (possibly empty, but never * {@code null}). */ List getSeriesKeys(); /** * Returns the key for the specified series. * * @param index the series index. * * @return The series key. * * @since 1.3 */ S getSeriesKey(int index); /** * Returns the index of the specified series key, or {@code -1} if * the key is not found. * * @param key the key ({@code null} not permitted). * * @return The index of the key, or {@code -1}. */ int getSeriesIndex(S key); /** * Returns the number of items in a given series. * * @param series the series index. * * @return The item count. */ int getItemCount(int series); /** * Returns the x-value for an item in a series. * * @param series the series index. * @param item the item index. * * @return The x-value. */ double getX(int series, int item); /** * Returns the y-value for an item in a series. * * @param series the series index. * @param item the item index. * * @return The y-value. */ double getY(int series, int item); /** * Returns the z-value for an item in a series. * * @param series the series index. * @param item the item index. * * @return The z-value. */ double getZ(int series, int item); } orson-charts-2.1.0/src/main/java/org/jfree/chart3d/data/xyz/XYZDatasetUtils.java000066400000000000000000000072641417331271500274460ustar00rootroot00000000000000/* =========================================================== * Orson Charts : a 3D chart library for the Java(tm) platform * =========================================================== * * (C)opyright 2013-2022, by David Gilbert. All rights reserved. * * https://github.com/jfree/orson-charts * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . * * [Oracle and Java are registered trademarks of Oracle and/or its affiliates. * Other names may be trademarks of their respective owners.] * * If you do not wish to be bound by the terms of the GPL, an alternative * commercial license can be purchased. For details, please see visit the * Orson Charts home page: * * http://www.object-refinery.com/orsoncharts/index.html * */ package org.jfree.chart3d.data.xyz; import org.jfree.chart3d.data.Range; import org.jfree.chart3d.data.function.Function3D; /** * A collection of utility methods related to {@link XYZDataset}. */ public class XYZDatasetUtils { /** * Creates an {@link XYZDataset} by sampling a {@link Function3D} over * a specified range. * * @param f the function ({@code null} not permitted). * @param key the series key ({@code null} not permitted). * @param xrange the range of x values ({@code null} not permitted). * @param xcount the number of x samples (must be at least 2). * @param zrange the range of z values ({@code null} not permitted). * @param zcount the number of z-samples (must be at least 2). * * @return A dataset containing sampled values from the function. */ public static XYZDataset sampleFunction(Function3D f, String key, Range xrange, double xcount, Range zrange, double zcount) { return sampleFunction(f, key, xrange.getMin(), xrange.getMax(), xcount, zrange.getMin(), zrange.getMax(), zcount); } /** * Creates an {@link XYZDataset} by sampling a {@link Function3D} over * a specified range. * * @param f the function ({@code null} not permitted). * @param key the series key ({@code null} not permitted). * @param xmin the lower bound of the x-range. * @param xmax the upper bound of the x-range. * @param xcount the number of x samples (must be at least 2). * @param zmin the lower bound of the z-range. * @param zmax the upper bound of the z-range. * @param zcount the number of z-samples (must be at least 2). * * @return A dataset containing sampled values from the function. */ public static XYZDataset sampleFunction(Function3D f, String key, double xmin, double xmax, double xcount, double zmin, double zmax, double zcount) { XYZSeries s = new XYZSeries<>(key); for (double x = xmin; x <= xmax; x += (xmax - xmin) / xcount) { for (double z = zmin; z <= zmax; z += (zmax - zmin) / zcount) { s.add(x, f.getValue(x, z), z); } } XYZSeriesCollection dataset = new XYZSeriesCollection<>(); dataset.add(s); return dataset; } } orson-charts-2.1.0/src/main/java/org/jfree/chart3d/data/xyz/XYZItemKey.java000066400000000000000000000103071417331271500263770ustar00rootroot00000000000000/* =========================================================== * Orson Charts : a 3D chart library for the Java(tm) platform * =========================================================== * * (C)opyright 2013-2022, by David Gilbert. All rights reserved. * * https://github.com/jfree/orson-charts * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . * * [Oracle and Java are registered trademarks of Oracle and/or its affiliates. * Other names may be trademarks of their respective owners.] * * If you do not wish to be bound by the terms of the GPL, an alternative * commercial license can be purchased. For details, please see visit the * Orson Charts home page: * * http://www.object-refinery.com/orsoncharts/index.html * */ package org.jfree.chart3d.data.xyz; import java.io.Serializable; import org.jfree.chart3d.data.ItemKey; import org.jfree.chart3d.internal.Args; import org.jfree.chart3d.internal.ObjectUtils; /** * An object that references one data item in an {@link XYZDataset}. This is * used internally to track the data item that a 3D object is related to, if * any (and later that link is used for chart interaction). Instances of * this class are immutable. * * @param The series key type. * * @since 1.3 */ public class XYZItemKey> implements ItemKey, Comparable>, Serializable { /** A key identifying a series in the dataset. */ private final S seriesKey; /** The index of an item within a series. */ private final int itemIndex; /** * Creates a new instance. * * @param seriesKey the series key ({@code null} not permitted). * @param itemIndex the item index. */ public XYZItemKey(S seriesKey, int itemIndex) { Args.nullNotPermitted(seriesKey, "seriesKey"); this.seriesKey = seriesKey; this.itemIndex = itemIndex; } /** * Returns the series key. * * @return The series key (never {@code null}). */ public S getSeriesKey() { return this.seriesKey; } /** * Returns the item index. * * @return The item index. */ public int getItemIndex() { return this.itemIndex; } /** * Tests this instance for equality with an arbitrary object. * * @param obj the object to test ({@code null} permitted). * * @return A boolean. */ @Override public boolean equals(Object obj) { if (obj == this) { return true; } if (!(obj instanceof XYZItemKey)) { return false; } XYZItemKey that = (XYZItemKey) obj; if (!this.seriesKey.equals(that.seriesKey)) { return false; } if (this.itemIndex != that.itemIndex) { return false; } return true; } @Override public int hashCode() { int hash = 7; hash = 41 * hash + ObjectUtils.hashCode(this.seriesKey); hash = 41 * hash + this.itemIndex; return hash; } @Override public String toJSONString() { return "{\"seriesKey\": \"" + this.seriesKey.toString() + "\", " + "\"itemIndex\": " + this.itemIndex + "}"; } @Override public String toString() { return "XYZItemKey[seriesKey=" + this.seriesKey.toString() + ",item=" + itemIndex + "]"; } @Override public int compareTo(XYZItemKey key) { int result = this.seriesKey.compareTo(key.seriesKey); if (result == 0) { result = this.itemIndex - key.itemIndex; } return result; } } orson-charts-2.1.0/src/main/java/org/jfree/chart3d/data/xyz/XYZItemKeys.java000066400000000000000000000047701417331271500265710ustar00rootroot00000000000000/* =========================================================== * Orson Charts : a 3D chart library for the Java(tm) platform * =========================================================== * * (C)opyright 2013-2022, by David Gilbert. All rights reserved. * * https://github.com/jfree/orson-charts * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . * * [Oracle and Java are registered trademarks of Oracle and/or its affiliates. * Other names may be trademarks of their respective owners.] * * If you do not wish to be bound by the terms of the GPL, an alternative * commercial license can be purchased. For details, please see visit the * Orson Charts home page: * * http://www.object-refinery.com/orsoncharts/index.html * */ package org.jfree.chart3d.data.xyz; import org.jfree.chart3d.internal.Args; import java.util.ArrayList; import java.util.Collection; /** * Utility methods. * * @since 1.3 */ public class XYZItemKeys { /** * Returns a collection of item keys extracted from one series in the * specified dataset. * * @param dataset the dataset ({@code null} not permitted). * @param seriesKey the series key ({@code null} not permitted). * * @param the type of the series key. * * @return A boolean. */ public static > Collection> itemKeysForSeries(XYZDataset dataset, S seriesKey) { Args.nullNotPermitted(dataset, "dataset"); Args.nullNotPermitted(seriesKey, "seriesKey"); Collection> result = new ArrayList<>(); int seriesIndex = dataset.getSeriesIndex(seriesKey); if (seriesIndex > 0) { return result; } for (int i = 0; i < dataset.getItemCount(seriesIndex); i++) { XYZItemKey key = new XYZItemKey<>(seriesKey, i); result.add(key); } return result; } } orson-charts-2.1.0/src/main/java/org/jfree/chart3d/data/xyz/XYZSeries.java000066400000000000000000000223201417331271500262600ustar00rootroot00000000000000/* =========================================================== * Orson Charts : a 3D chart library for the Java(tm) platform * =========================================================== * * (C)opyright 2013-2022, by David Gilbert. All rights reserved. * * https://github.com/jfree/orson-charts * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . * * [Oracle and Java are registered trademarks of Oracle and/or its affiliates. * Other names may be trademarks of their respective owners.] * * If you do not wish to be bound by the terms of the GPL, an alternative * commercial license can be purchased. For details, please see visit the * Orson Charts home page: * * http://www.object-refinery.com/orsoncharts/index.html * */ package org.jfree.chart3d.data.xyz; import java.io.Serializable; import java.util.ArrayList; import java.util.List; import javax.swing.event.EventListenerList; import org.jfree.chart3d.data.Series3DChangeEvent; import org.jfree.chart3d.data.Series3DChangeListener; import org.jfree.chart3d.internal.Args; import org.jfree.chart3d.internal.ObjectUtils; /** * A data series containing a sequence of {@code (x, y, z)} data items. * The series has an immutable key to identify it, and can be added to an * {@link XYZSeriesCollection} to create a dataset. When a series is part * of an {@link XYZSeriesCollection}, the collection will register with the * series to receive change events - in this way, the collection can notify * its own listeners when a change is made to the series. *

* NOTE: This class is serializable, but the serialization format is subject * to change in future releases and should not be relied upon for persisting * instances of this class. * * @param the type for the series key (it is recommended that this is a * class of immutable objects, because the series key should never be * modified). */ @SuppressWarnings("serial") public class XYZSeries> implements Serializable { /** The series key (never {@code null}). */ private final K key; /** The data items in the series. */ private final List items; /** Storage for registered change listeners. */ private EventListenerList listeners; /** A flag that controls whether or not changes are notified. */ private boolean notify; /** * Creates a new series with the specified key. Note that the series key * cannot be changed after it has been set in the constructor - this is by * design, to ensure that each series in a {@link XYZSeriesCollection} * always has a unique key. For the same reason, the key type should be * an immutable class. * * @param key the key ({@code null} not permitted). */ public XYZSeries(K key) { Args.nullNotPermitted(key, "key"); this.key = key; this.items = new ArrayList<>(); this.listeners = new EventListenerList(); this.notify = true; } /** * Returns the series key. * * @return The series key (never {@code null}). */ public K getKey() { return this.key; } /** * Returns the number of items in the series. * * @return The number of items in the series. */ public int getItemCount() { return this.items.size(); } /** * Returns a list containing all the items for the dataset (a new list * is created each time this method is called, so the list can be freely * modified without affecting the state of this series). * * @return A list of all items. * * @since 1.6 */ public List getItems() { return new ArrayList<>(this.items); } /** * Returns the x-value for the specified item in the series. * * @param itemIndex the item index. * * @return The x-value. */ public double getXValue(int itemIndex) { return this.items.get(itemIndex).getX(); } /** * Returns the y-value for the specified item in the series. * * @param itemIndex the item index. * * @return The y-value. */ public double getYValue(int itemIndex) { return this.items.get(itemIndex).getY(); } /** * Returns the z-value for the specified item in the series. * * @param itemIndex the item index. * * @return The z-value. */ public double getZValue(int itemIndex) { return this.items.get(itemIndex).getZ(); } /** * Adds a new data item to the series and sends a * {@link Series3DChangeEvent} to all registered listeners. * * @param x the x-value. * @param y the y-value. * @param z the z-value. */ public void add(double x, double y, double z) { add(new XYZDataItem(x, y, z)); } /** * Adds a new data item to the series and sends a * {@link Series3DChangeEvent} to all registered listeners. * * @param item the data item ({@code null} not permitted). */ public void add(XYZDataItem item) { Args.nullNotPermitted(item, "item"); this.items.add(item); fireSeriesChanged(); } /** * Removes a data item from the series and sends a * {@link Series3DChangeEvent} to all registered listeners. * * @param itemIndex the item index. * * @since 1.6 */ public void remove(int itemIndex) { this.items.remove(itemIndex); fireSeriesChanged(); } /** * Registers an object with this series, to receive notification whenever * the series changes. *

* Objects being registered must implement the * {@link Series3DChangeListener} interface. * * @param listener the listener to register. * * @since 1.6 */ public void addChangeListener(Series3DChangeListener listener) { this.listeners.add(Series3DChangeListener.class, listener); } /** * Deregisters an object, so that it not longer receives notification * whenever the series changes. * * @param listener the listener to deregister. * * @since 1.6 */ public void removeChangeListener(Series3DChangeListener listener) { this.listeners.remove(Series3DChangeListener.class, listener); } /** * Returns the flag that controls whether or not change events are sent to * registered listeners. * * @return A boolean. * * @see #setNotify(boolean) * @since 1.6 */ public boolean getNotify() { return this.notify; } /** * Sets the flag that controls whether or not change events are sent to * registered listeners. * * @param notify the new value of the flag. * * @see #getNotify() * @since 1.6 */ public void setNotify(boolean notify) { if (this.notify != notify) { this.notify = notify; if (notify) { fireSeriesChanged(); } } } /** * General method for signaling to registered listeners that the series * has been changed. * * @since 1.6 */ public void fireSeriesChanged() { if (this.notify) { notifyListeners(new Series3DChangeEvent(this)); } } /** * Sends a change event to all registered listeners. * * @param event contains information about the event that triggered the * notification. * * @since 1.6 */ protected void notifyListeners(Series3DChangeEvent event) { Object[] listenerList = this.listeners.getListenerList(); for (int i = listenerList.length - 2; i >= 0; i -= 2) { if (listenerList[i] == Series3DChangeListener.class) { ((Series3DChangeListener) listenerList[i + 1]).seriesChanged( event); } } } /** * Tests this series for equality with an arbitrary object. * * @param obj the object to test ({@code null} permitted). * * @return A boolean. */ @Override public boolean equals(Object obj) { if (obj == this) { return true; } if (!(obj instanceof XYZSeries)) { return false; } XYZSeries that = (XYZSeries) obj; if (!this.key.equals(that.key)) { return false; } if (!this.items.equals(that.items)) { return false; } return true; } @Override public int hashCode() { int hash = 7; hash = 41 * hash + ObjectUtils.hashCode(this.key); return hash; } } orson-charts-2.1.0/src/main/java/org/jfree/chart3d/data/xyz/XYZSeriesCollection.java000066400000000000000000000235771417331271500303130ustar00rootroot00000000000000/* =========================================================== * Orson Charts : a 3D chart library for the Java(tm) platform * =========================================================== * * (C)opyright 2013-2022, by David Gilbert. All rights reserved. * * https://github.com/jfree/orson-charts * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . * * [Oracle and Java are registered trademarks of Oracle and/or its affiliates. * Other names may be trademarks of their respective owners.] * * If you do not wish to be bound by the terms of the GPL, an alternative * commercial license can be purchased. For details, please see visit the * Orson Charts home page: * * http://www.object-refinery.com/orsoncharts/index.html * */ package org.jfree.chart3d.data.xyz; import java.io.Serializable; import java.util.ArrayList; import java.util.List; import org.jfree.chart3d.internal.Args; import org.jfree.chart3d.data.AbstractDataset3D; import org.jfree.chart3d.data.Dataset3DChangeEvent; import org.jfree.chart3d.data.JSONUtils; import org.jfree.chart3d.data.Series3DChangeEvent; import org.jfree.chart3d.data.Series3DChangeListener; import org.jfree.chart3d.internal.ObjectUtils; import org.jfree.chart3d.plot.XYZPlot; import org.jfree.chart3d.renderer.xyz.XYZRenderer; /** * A collection of {@link XYZSeries} objects (implements the {@link XYZDataset} * interface so that it can be used as a source of data for an * {@link XYZRenderer} on an {@link XYZPlot}). *

* NOTE: This class is serializable, but the serialization format is subject * to change in future releases and should not be relied upon for persisting * instances of this class. */ @SuppressWarnings("serial") public class XYZSeriesCollection> extends AbstractDataset3D implements XYZDataset, Series3DChangeListener, Serializable { /** Storage for the data series. */ private final List> series; /** * Creates a new (empty) {@code XYZSeriesCollection} instance. */ public XYZSeriesCollection() { this.series = new ArrayList<>(); } /** * Returns the number of series in the collection. * * @return The number of series in the collection. */ @Override public int getSeriesCount() { return this.series.size(); } /** * Returns the index of the series with the specified key, or * {@code -1} if there is no series with the specified key. * * @param key the key ({@code null} not permitted). * * @return The series index or {@code -1}. */ @Override public int getSeriesIndex(S key) { Args.nullNotPermitted(key, "key"); return getSeriesKeys().indexOf(key); } /** * Returns a new list containing all the series keys. Modifying this list * will have no impact on the {@code XYZSeriesCollection} instance. * * @return A list containing the series keys (possibly empty, but never * {@code null}). */ @Override public List getSeriesKeys() { List result = new ArrayList<>(); for (XYZSeries s : this.series) { result.add(s.getKey()); } return result; } /** * Returns the key for the specified series. * * @param seriesIndex the series index. * * @return The series key. * * @since 1.3 */ @Override public S getSeriesKey(int seriesIndex) { return getSeries(seriesIndex).getKey(); } /** * Adds a series to the collection (note that the series key must be * unique within the collection). The collection will automatically * register to receive change events from the series, and fire a * {@link Dataset3DChangeEvent} whenever the data in the series changes. * * @param series the series ({@code null} not permitted). */ public void add(XYZSeries series) { Args.nullNotPermitted(series, "series"); if (getSeriesIndex(series.getKey()) >= 0) { throw new IllegalArgumentException("Another series with the same key already exists within the collection."); } this.series.add(series); series.addChangeListener(this); fireDatasetChanged(); } /** * Removes a series from the collection and sends a * {@link Dataset3DChangeEvent} to all registered listeners. * * @param seriesIndex the series index. * * @since 1.6 */ public void remove(int seriesIndex) { XYZSeries s = getSeries(seriesIndex); remove(s); } /** * Removes a series from the collection and sends a * {@link Dataset3DChangeEvent} to all registered listeners. If the series * is not part of the collection, this method does nothing. * * @param series the series ({@code null} not permitted). * * @since 1.6 */ public void remove(XYZSeries series) { Args.nullNotPermitted(series, "series"); if (this.series.contains(series)) { series.removeChangeListener(this); this.series.remove(series); fireDatasetChanged(); } } /** * Removes all the series from the collection and sends a * {@link Dataset3DChangeEvent} to all registered listeners. If the * collection is already empty, this method does nothing. */ public void removeAll() { if (!this.series.isEmpty()) { for (XYZSeries s : this.series) { s.removeChangeListener(this); } this.series.clear(); fireDatasetChanged(); } } /** * Returns the series with the specified index. * * @param index the series index. * * @return The series. * * @since 1.2 */ public XYZSeries getSeries(int index) { Args.checkArrayBounds(index, "index", this.series.size()); return this.series.get(index); } /** * Returns the series with the specified key, or {@code null} if * there is no such series. * * @param key the key ({@code null} not permitted). * * @return The series. * * @since 1.2 */ public XYZSeries getSeries(Comparable key) { Args.nullNotPermitted(key, "key"); for (XYZSeries s : this.series) { if (s.getKey().equals(key)) { return s; } } return null; } /** * Returns the number of items in the specified series. * * @param seriesIndex the series index. * * @return The number of items in the specified series. */ @Override public int getItemCount(int seriesIndex) { XYZSeries s = this.series.get(seriesIndex); return s.getItemCount(); } /** * Returns the x-value for one item in a series. * * @param seriesIndex the series index. * @param itemIndex the item index. * * @return The x-value. */ @Override public double getX(int seriesIndex, int itemIndex) { XYZSeries s = this.series.get(seriesIndex); return s.getXValue(itemIndex); } /** * Returns the y-value for one item in a series. * * @param seriesIndex the series index. * @param itemIndex the item index. * * @return The y-value. */ @Override public double getY(int seriesIndex, int itemIndex) { XYZSeries s = this.series.get(seriesIndex); return s.getYValue(itemIndex); } /** * Returns the z-value for one item in a series. * * @param seriesIndex the series index. * @param itemIndex the item index. * * @return The z-value. */ @Override public double getZ(int seriesIndex, int itemIndex) { XYZSeries s = this.series.get(seriesIndex); return s.getZValue(itemIndex); } /** * Called when an observed series changes in some way. * * @param event information about the change. * * @since 1.6 */ @Override public void seriesChanged(Series3DChangeEvent event) { fireDatasetChanged(); } /** * Tests this dataset for equality with an arbitrary object. * * @param obj the object ({@code null} not permitted). * * @return A boolean. */ @Override public boolean equals(Object obj) { if (obj == this) { return true; } if (!(obj instanceof XYZSeriesCollection)) { return false; } XYZSeriesCollection that = (XYZSeriesCollection) obj; if (!this.series.equals(that.series)) { return false; } return true; } @Override public int hashCode() { int hash = 5; hash = 59 * hash + ObjectUtils.hashCode(this.series); return hash; } /** * Returns a string representation of this instance, primarily for * debugging purposes. *

* Implementation note: the current implementation (which is subject to * change) writes the dataset in JSON format using * {@link JSONUtils#writeXYZDataset(org.jfree.chart3d.data.xyz.XYZDataset)}. * * @return A string. */ @Override public String toString() { return JSONUtils.writeXYZDataset(this); } } orson-charts-2.1.0/src/main/java/org/jfree/chart3d/data/xyz/package-info.java000066400000000000000000000002021417331271500267320ustar00rootroot00000000000000/** * Datasets that can be used by the {@link org.jfree.chart3d.plot.XYZPlot} * class. */ package org.jfree.chart3d.data.xyz; orson-charts-2.1.0/src/main/java/org/jfree/chart3d/export/000077500000000000000000000000001417331271500233275ustar00rootroot00000000000000orson-charts-2.1.0/src/main/java/org/jfree/chart3d/export/ExportFormat.java000066400000000000000000000036351417331271500266330ustar00rootroot00000000000000/* =========================================================== * Orson Charts : a 3D chart library for the Java(tm) platform * =========================================================== * * (C)opyright 2013-2022, by David Gilbert. All rights reserved. * * https://github.com/jfree/orson-charts * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . * * [Oracle and Java are registered trademarks of Oracle and/or its affiliates. * Other names may be trademarks of their respective owners.] * * If you do not wish to be bound by the terms of the GPL, an alternative * commercial license can be purchased. For details, please see visit the * Orson Charts home page: * * http://www.object-refinery.com/orsoncharts/index.html * */ package org.jfree.chart3d.export; /** * An enumeration of the different export formats supported by Orson Charts. * PNG and JPEG export are provided by the Java standard library. PDF export * is enabled when JFreePDF is available on the classpath, and SVG export is * enabled when JFreeSVG is available on the classpath. * * @since 1.2 */ public enum ExportFormat { /** The PNG image format. */ PNG, /** The JPEG image format. */ JPEG, /** The Acrobat Portable Document Format. */ PDF, /** The Scalable Vector Graphics format. */ SVG } orson-charts-2.1.0/src/main/java/org/jfree/chart3d/export/ExportFormats.java000066400000000000000000000051671417331271500270200ustar00rootroot00000000000000/* =========================================================== * Orson Charts : a 3D chart library for the Java(tm) platform * =========================================================== * * (C)opyright 2013-2022, by David Gilbert. All rights reserved. * * https://github.com/jfree/orson-charts * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . * * [Oracle and Java are registered trademarks of Oracle and/or its affiliates. * Other names may be trademarks of their respective owners.] * * If you do not wish to be bound by the terms of the GPL, an alternative * commercial license can be purchased. For details, please see visit the * Orson Charts home page: * * http://www.object-refinery.com/orsoncharts/index.html * */ package org.jfree.chart3d.export; /** * Utility methods related to export formats. * * @since 1.2 */ public class ExportFormats { /** * Returns {@code true} if JFreeSVG is on the classpath, and * {@code false} otherwise. The JFreeSVG library can be found at * http://www.jfree.org/jfreesvg/ * * @return A boolean. * * @since 1.2 */ public static boolean isJFreeSVGAvailable() { Class svgClass = null; try { svgClass = Class.forName("org.jfree.svg.SVGGraphics2D"); } catch (ClassNotFoundException e) { // svgClass will be null so the function will return false } return (svgClass != null); } /** * Returns {@code true} if {@code JFreePDF} is on the classpath, and * {@code false} otherwise. The JFreePDF library can be found at * https://github.com/jfree/jfreepdf * * @return A boolean. */ public static boolean isJFreePDFAvailable() { Class pdfDocumentClass = null; try { pdfDocumentClass = Class.forName("org.jfree.pdf.PDFDocument"); } catch (ClassNotFoundException e) { // pdfDocument class will be null so the function will return false } return (pdfDocumentClass != null); } } orson-charts-2.1.0/src/main/java/org/jfree/chart3d/export/ExportUtils.java000066400000000000000000000210421417331271500264730ustar00rootroot00000000000000/* =========================================================== * Orson Charts : a 3D chart library for the Java(tm) platform * =========================================================== * * (C)opyright 2013-2022, by David Gilbert. All rights reserved. * * https://github.com/jfree/orson-charts * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . * * [Oracle and Java are registered trademarks of Oracle and/or its affiliates. * Other names may be trademarks of their respective owners.] * * If you do not wish to be bound by the terms of the GPL, an alternative * commercial license can be purchased. For details, please see visit the * Orson Charts home page: * * http://www.object-refinery.com/orsoncharts/index.html * */ package org.jfree.chart3d.export; import java.awt.Graphics2D; import java.awt.Rectangle; import java.awt.geom.Rectangle2D; import java.awt.image.BufferedImage; import java.io.BufferedOutputStream; import java.io.File; import java.io.FileNotFoundException; import java.io.FileOutputStream; import java.io.IOException; import java.io.OutputStream; import java.lang.reflect.Constructor; import java.lang.reflect.InvocationTargetException; import java.lang.reflect.Method; import javax.imageio.ImageIO; import org.jfree.chart3d.graphics3d.Drawable3D; import org.jfree.chart3d.graphics3d.RenderingInfo; import org.jfree.chart3d.internal.Args; /** * Export utility methods. * * @since 1.4 */ public class ExportUtils { /** * Writes the current content to the specified file in SVG format. This * will only work when the JFreeSVG library is found on the classpath. * Reflection is used to ensure there is no compile-time dependency on * JFreeSVG. Any exceptions that occur while writing the file are * caught and wrapped in a {@code RuntimeException} that is then thrown. * * @param drawable the drawable ({@code null} not permitted). * @param w the chart width. * @param h the chart height. * @param file the output file ({@code null} not permitted). * * @return The rendering info. */ public static RenderingInfo writeAsSVG(Drawable3D drawable, int w, int h, File file) { if (!ExportFormats.isJFreeSVGAvailable()) { throw new IllegalStateException( "JFreeSVG is not present on the classpath."); } Args.nullNotPermitted(drawable, "drawable"); Args.nullNotPermitted(file, "file"); try { Class svg2Class = Class.forName( "org.jfree.svg.SVGGraphics2D"); Constructor c1 = svg2Class.getConstructor(double.class, double.class); Graphics2D svg2 = (Graphics2D) c1.newInstance(w, h); Rectangle2D drawArea = new Rectangle2D.Double(0, 0, w, h); RenderingInfo info = drawable.draw(svg2, drawArea); Class svgUtilsClass = Class.forName( "org.jfree.svg.SVGUtils"); Method m1 = svg2Class.getMethod("getSVGElement", (Class[]) null); String element = (String) m1.invoke(svg2, (Object[]) null); Method m2 = svgUtilsClass.getMethod("writeToSVG", File.class, String.class); m2.invoke(svgUtilsClass, file, element); return info; } catch (ClassNotFoundException | InstantiationException | IllegalAccessException | NoSuchMethodException | SecurityException | IllegalArgumentException | InvocationTargetException ex) { throw new RuntimeException(ex); } } /** * Writes a {@link Drawable3D} to the specified file in PDF format. This * will only work when the OrsonPDF library is found on the classpath. * Reflection is used to ensure there is no compile-time dependency on * OrsonPDF. Any exceptions that occur while writing the file are * caught and wrapped in a {@code RuntimeException} that is then thrown. * * @param drawable the drawable ({code null} not permitted). * @param w the chart width. * @param h the chart height. * @param file the output file ({code null} not permitted). * * @return The rendering info. */ public static RenderingInfo writeAsPDF(Drawable3D drawable, int w, int h, File file) { if (!ExportFormats.isJFreePDFAvailable()) { throw new IllegalStateException( "JFreePDF is not present on the classpath."); } Args.nullNotPermitted(drawable, "drawable"); Args.nullNotPermitted(file, "file"); try { Class pdfDocClass = Class.forName("org.jfree.pdf.PDFDocument"); Object pdfDoc = pdfDocClass.getDeclaredConstructor().newInstance(); Method m = pdfDocClass.getMethod("createPage", Rectangle2D.class); Rectangle2D rect = new Rectangle(w, h); Object page = m.invoke(pdfDoc, rect); Method m2 = page.getClass().getMethod("getGraphics2D"); Graphics2D g2 = (Graphics2D) m2.invoke(page); Rectangle2D drawArea = new Rectangle2D.Double(0, 0, w, h); RenderingInfo info = drawable.draw(g2, drawArea); Method m3 = pdfDocClass.getMethod("writeToFile", File.class); m3.invoke(pdfDoc, file); return info; } catch (ClassNotFoundException | InstantiationException ex) { throw new RuntimeException(ex); } catch (IllegalAccessException ex) { throw new RuntimeException(ex); } catch (NoSuchMethodException ex) { throw new RuntimeException(ex); } catch (SecurityException ex) { throw new RuntimeException(ex); } catch (IllegalArgumentException ex) { throw new RuntimeException(ex); } catch (InvocationTargetException ex) { throw new RuntimeException(ex); } } /** * Writes the current content to the specified file in PNG format. * * @param drawable the drawable ({@code null} not permitted). * @param w the chart width. * @param h the chart height. * @param file the output file ({@code null} not permitted). * * @return The rendering info. * * @throws FileNotFoundException if the file is not found. * @throws IOException if there is an I/O problem. */ public static RenderingInfo writeAsPNG(Drawable3D drawable, int w, int h, File file) throws FileNotFoundException, IOException { BufferedImage image = new BufferedImage(w, h, BufferedImage.TYPE_INT_ARGB); Graphics2D g2 = image.createGraphics(); RenderingInfo result = drawable.draw(g2, new Rectangle(w, h)); OutputStream out = new BufferedOutputStream(new FileOutputStream(file)); try { ImageIO.write(image, "png", out); } finally { out.close(); } return result; } /** * Writes the current content to the specified file in JPEG format. * * @param drawable the drawable ({@code null} not permitted). * @param w the chart width. * @param h the chart height. * @param file the output file ({@code null} not permitted). * * @return The rendering info. * * @throws FileNotFoundException if the file is not found. * @throws IOException if there is an I/O problem. */ public static RenderingInfo writeAsJPEG(Drawable3D drawable, int w, int h, File file) throws FileNotFoundException, IOException { BufferedImage image = new BufferedImage(w, h, BufferedImage.TYPE_INT_RGB); Graphics2D g2 = image.createGraphics(); RenderingInfo result = drawable.draw(g2, new Rectangle(w, h)); OutputStream out = new BufferedOutputStream(new FileOutputStream(file)); try { ImageIO.write(image, "jpg", out); } finally { out.close(); } return result; } } orson-charts-2.1.0/src/main/java/org/jfree/chart3d/export/package-info.java000066400000000000000000000001131417331271500265110ustar00rootroot00000000000000/** * Classes for exporting charts. */ package org.jfree.chart3d.export; orson-charts-2.1.0/src/main/java/org/jfree/chart3d/graphics2d/000077500000000000000000000000001417331271500240345ustar00rootroot00000000000000orson-charts-2.1.0/src/main/java/org/jfree/chart3d/graphics2d/Anchor2D.java000066400000000000000000000217621417331271500263070ustar00rootroot00000000000000/* =========================================================== * Orson Charts : a 3D chart library for the Java(tm) platform * =========================================================== * * (C)opyright 2013-2022, by David Gilbert. All rights reserved. * * https://github.com/jfree/orson-charts * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . * * [Oracle and Java are registered trademarks of Oracle and/or its affiliates. * Other names may be trademarks of their respective owners.] * * If you do not wish to be bound by the terms of the GPL, an alternative * commercial license can be purchased. For details, please see visit the * Orson Charts home page: * * http://www.object-refinery.com/orsoncharts/index.html * */ package org.jfree.chart3d.graphics2d; import java.awt.geom.Point2D; import java.awt.geom.Rectangle2D; import java.io.Serializable; import org.jfree.chart3d.TitleAnchor; import org.jfree.chart3d.graphics3d.Offset2D; import org.jfree.chart3d.internal.Args; import org.jfree.chart3d.legend.LegendAnchor; /** * Represents an anchor point for a chart title and/or legend. The anchor * point is defined relative to a reference rectangle, the dimensions of which * are not known in advance (typically the reference rectangle is the bounding * rectangle of a chart that is being drawn). Some predefined anchor points * are provided in the {@link TitleAnchor} and {@link LegendAnchor} classes. *

* Instances of this class are immutable. *

* NOTE: This class is serializable, but the serialization format is subject * to change in future releases and should not be relied upon for persisting * instances of this class. */ @SuppressWarnings("serial") public final class Anchor2D implements Serializable { /** * An anchor point at the top left with zero offset from the target * rectangle bounds. * * @since 1.1 */ public static final Anchor2D TOP_LEFT = new Anchor2D(RefPt2D.TOP_LEFT, Offset2D.ZERO_OFFSET); /** * An anchor point at the top center with zero offset from the target * rectangle bounds. * * @since 1.1 */ public static final Anchor2D TOP_CENTER = new Anchor2D(RefPt2D.TOP_CENTER, Offset2D.ZERO_OFFSET); /** * An anchor point at the top right with zero offset from the target * rectangle bounds. * * @since 1.1 */ public static final Anchor2D TOP_RIGHT = new Anchor2D(RefPt2D.TOP_RIGHT, Offset2D.ZERO_OFFSET); /** * An anchor point at the center left with zero offset from the target * rectangle bounds. * * @since 1.1 */ public static final Anchor2D CENTER_LEFT = new Anchor2D(RefPt2D.CENTER_LEFT, Offset2D.ZERO_OFFSET); /** * An anchor point at the center of the target rectangle. * * @since 1.1 */ public static final Anchor2D CENTER = new Anchor2D(RefPt2D.CENTER, Offset2D.ZERO_OFFSET); /** * An anchor point at the center right with zero offset from the target * rectangle bounds. * * @since 1.1 */ public static final Anchor2D CENTER_RIGHT = new Anchor2D(RefPt2D.CENTER_RIGHT, Offset2D.ZERO_OFFSET); /** * An anchor point at the bottom left with zero offset from the target * rectangle bounds. * * @since 1.1 */ public static final Anchor2D BOTTOM_LEFT = new Anchor2D(RefPt2D.BOTTOM_LEFT, Offset2D.ZERO_OFFSET); /** * An anchor point at the bottom center with zero offset from the target * rectangle bounds. * * @since 1.1 */ public static final Anchor2D BOTTOM_CENTER = new Anchor2D(RefPt2D.BOTTOM_CENTER, Offset2D.ZERO_OFFSET); /** * An anchor point at the bottom right with zero offset from the target * rectangle bounds. * * @since 1.1 */ public static final Anchor2D BOTTOM_RIGHT = new Anchor2D(RefPt2D.BOTTOM_RIGHT, Offset2D.ZERO_OFFSET); /** * The reference point relative to some bounding rectangle, normally the * bounds of the chart (never {@code null}). */ private final RefPt2D refPt; /** * The offsets to apply (never {@code null}). */ private final Offset2D offset; /** * Creates a default instance. */ public Anchor2D() { this(RefPt2D.TOP_LEFT); } /** * Creates a new {@code Anchor2D} instance with the specified * reference point and offsets of {@code (4.0, 4.0)}. * * @param refPt the reference point ({@code null} not permitted). */ public Anchor2D(RefPt2D refPt) { this(refPt, new Offset2D(4.0, 4.0)); } /** * Creates a new anchor. * * @param refPt the reference point ({@code null} not permitted). * @param offset the offset ({@code null} not permitted). */ public Anchor2D(RefPt2D refPt, Offset2D offset) { Args.nullNotPermitted(refPt, "refPt"); Args.nullNotPermitted(offset, "offset"); this.refPt = refPt; this.offset = offset; } /** * Returns the reference point. * * @return The reference point (never {@code null}). */ public RefPt2D getRefPt() { return this.refPt; } /** * Returns the offsets. * * @return The offsets (never {@code null}). */ public Offset2D getOffset() { return this.offset; } /** * Returns the anchor point for the given rectangle. * * @param rect the reference rectangle ({@code null} not permitted). * * @return The anchor point. */ public Point2D getAnchorPoint(Rectangle2D rect) { Args.nullNotPermitted(rect, "rect"); double x = 0.0; double y = 0.0; if (this.refPt.isLeft()) { x = rect.getX() + this.offset.getDX(); } else if (this.refPt.isHorizontalCenter()) { x = rect.getCenterX(); } else if (this.refPt.isRight()) { x = rect.getMaxX() - this.offset.getDX(); } if (this.refPt.isTop()) { y = rect.getMinY() + this.offset.getDY(); } else if (this.refPt.isVerticalCenter()) { y = rect.getCenterY(); } else if (this.refPt.isBottom()) { y = rect.getMaxY() - this.offset.getDY(); } return new Point2D.Double(x, y); } /** * Resolves the anchor to a specific point relative to a rectangle defined * by the points (startX, startY) and (endX, endY). * * @param startX the x-coordinate for the bottom left corner of the target * rect. * @param startY the y-coordinate for the bottom left corner of the target * rect. * @param endX the x-coordinate for the top right corner of the target * rect. * @param endY the y-coordinate for the top right corner of the target * rect. * * @return The resolved point. * * @since 1.2 */ public Point2D resolveAnchorWithPercentOffset(double startX, double startY, double endX, double endY) { double x = 0.0; double y = 0.0; if (this.refPt.isLeft()) { x = startX + this.offset.getDX() * (endX - startX); } else if (this.refPt.isHorizontalCenter()) { x = (startX + endX) / 2.0; } else if (this.refPt.isRight()) { x = endX - this.offset.getDX() * (endX - startX); } if (this.refPt.isTop()) { y = endY - this.offset.getDY() * (endY - startY); } else if (this.refPt.isVerticalCenter()) { y = (startY + endY) / 2.0; } else if (this.refPt.isBottom()) { y = startY + this.offset.getDY() * (endY - startY); } return new Point2D.Double(x, y); } /** * Tests this instance for equality with an arbitrary object. * * @param obj the object ({@code null} not permitted). * * @return A boolean. */ @Override public boolean equals(Object obj) { if (obj == this) { return true; } if (!(obj instanceof Anchor2D)) { return false; } Anchor2D that = (Anchor2D) obj; if (!this.refPt.equals(that.refPt)) { return false; } if (!this.offset.equals(that.offset)) { return false; } return true; } } orson-charts-2.1.0/src/main/java/org/jfree/chart3d/graphics2d/Fit2D.java000066400000000000000000000220651417331271500256140ustar00rootroot00000000000000/* =========================================================== * Orson Charts : a 3D chart library for the Java(tm) platform * =========================================================== * * (C)opyright 2013-2022, by David Gilbert. All rights reserved. * * https://github.com/jfree/orson-charts * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . * * [Oracle and Java are registered trademarks of Oracle and/or its affiliates. * Other names may be trademarks of their respective owners.] * * If you do not wish to be bound by the terms of the GPL, an alternative * commercial license can be purchased. For details, please see visit the * Orson Charts home page: * * http://www.object-refinery.com/orsoncharts/index.html * */ package org.jfree.chart3d.graphics2d; import org.jfree.chart3d.internal.Args; import java.awt.geom.Dimension2D; import java.awt.geom.Point2D; import java.awt.geom.Rectangle2D; import java.io.Serializable; /** * A specification for the alignment and fitting of one rectangle (the source * rectangle) with reference to another (the target rectangle). Instances of * this class are immutable. *

* One application for this is to specify how the background image for a chart * should be aligned and scaled. *

* NOTE: This class is serializable, but the serialization format is subject * to change in future releases and should not be relied upon for persisting * instances of this class. */ @SuppressWarnings("serial") public class Fit2D implements Serializable { /** * Aligns a source rectangle to the center of a target rectangle, without * resizing it. * * @since 1.1 */ public static final Fit2D CENTER_NO_SCALING = new Fit2D(Anchor2D.CENTER, Scale2D.NONE); /** * Fits a source rectangle to the top left of a target rectangle, without * resizing it. * * @since 1.1 */ public static final Fit2D TOP_LEFT_NO_SCALING = new Fit2D(Anchor2D.TOP_LEFT, Scale2D.NONE); /** * Fits a source rectangle to the top center of a target rectangle, without * resizing it. * * @since 1.1 */ public static final Fit2D TOP_CENTER_NO_SCALING = new Fit2D(Anchor2D.TOP_CENTER, Scale2D.NONE); /** * Fits a source rectangle to the top right of a target rectangle, without * resizing it. * * @since 1.1 */ public static final Fit2D TOP_RIGHT_NO_SCALING = new Fit2D(Anchor2D.TOP_RIGHT, Scale2D.NONE); /** * Fits a source rectangle to the center left of a target rectangle, * without resizing it. * * @since 1.1 */ public static final Fit2D CENTER_LEFT_NO_SCALING = new Fit2D(Anchor2D.CENTER_LEFT, Scale2D.NONE); /** * Fits a source rectangle to the center right of a target rectangle, * without resizing it. * * @since 1.1 */ public static final Fit2D CENTER_RIGHT_NO_SCALING = new Fit2D(Anchor2D.CENTER_RIGHT, Scale2D.NONE); /** * Fits a source rectangle to the bottom left of a target rectangle, * without resizing it. * * @since 1.1 */ public static final Fit2D BOTTOM_LEFT_NO_SCALING = new Fit2D(Anchor2D.BOTTOM_LEFT, Scale2D.NONE); /** * Fits a source rectangle to the bottom center of a target rectangle, * without resizing it. * * @since 1.1 */ public static final Fit2D BOTTOM_CENTER_NO_SCALING = new Fit2D(Anchor2D.BOTTOM_CENTER, Scale2D.NONE); /** * Fits a source rectangle to the bottom right of a target rectangle, * without resizing it. * * @since 1.1 */ public static final Fit2D BOTTOM_RIGHT_NO_SCALING = new Fit2D(Anchor2D.BOTTOM_RIGHT, Scale2D.NONE); /** * Returns a fitter for the specified reference point. * * @param refPt the reference point ({@code null} not permitted). * * @return A fitter. * * @since 1.1 */ public static Fit2D getNoScalingFitter(RefPt2D refPt) { switch (refPt) { case TOP_LEFT : return Fit2D.TOP_LEFT_NO_SCALING; case TOP_CENTER : return Fit2D.TOP_CENTER_NO_SCALING; case TOP_RIGHT : return Fit2D.TOP_RIGHT_NO_SCALING; case CENTER_LEFT : return Fit2D.CENTER_LEFT_NO_SCALING; case CENTER : return Fit2D.CENTER_NO_SCALING; case CENTER_RIGHT : return Fit2D.CENTER_RIGHT_NO_SCALING; case BOTTOM_LEFT : return Fit2D.BOTTOM_LEFT_NO_SCALING; case BOTTOM_CENTER : return Fit2D.BOTTOM_CENTER_NO_SCALING; case BOTTOM_RIGHT : return Fit2D.BOTTOM_RIGHT_NO_SCALING; } throw new IllegalStateException("RefPt2D not recognised : " + refPt); } /** * Scale the source rectangle to fit the target rectangle. * * @since 1.1 */ public static final Fit2D SCALE_TO_FIT_TARGET = new Fit2D(Anchor2D.CENTER, Scale2D.SCALE_BOTH); /** The anchor point for alignment. */ private final Anchor2D anchor; /** The scaling to apply. */ private final Scale2D scale; /** * Creates a new instance. * * @param anchor the anchor point ({@code null} not permitted). * @param scale the scaling ({@code null} not permitted). */ public Fit2D(Anchor2D anchor, Scale2D scale) { Args.nullNotPermitted(anchor, "anchor"); Args.nullNotPermitted(scale, "scale"); this.anchor = anchor; this.scale = scale; } /** * Returns the anchor. * * @return The anchor (never {@code null}). * * @since 1.1 */ public Anchor2D getAnchor() { return this.anchor; } /** * Returns the scaling. * * @return The scaling (never {@code null}). * * @since 1.1 */ public Scale2D getScale() { return this.scale; } /** * Fits a rectangle of the specified dimension to the target rectangle, * aligning and scaling according to the attributes of this instance. * * @param srcDim the dimensions of the source rectangle ({@code null} * not permitted). * @param target the target rectangle ({@code null} not permitted). * * @return The bounds of the fitted rectangle (never {@code null}). */ public Rectangle2D fit(Dimension2D srcDim, Rectangle2D target) { Rectangle2D result = new Rectangle2D.Double(); if (this.scale == Scale2D.SCALE_BOTH) { result.setFrame(target); return result; } double width = srcDim.getWidth(); if (this.scale == Scale2D.SCALE_HORIZONTAL) { width = target.getWidth(); if (!this.anchor.getRefPt().isHorizontalCenter()) { width -= 2 * this.anchor.getOffset().getDX(); } } double height = srcDim.getHeight(); if (this.scale == Scale2D.SCALE_VERTICAL) { height = target.getHeight(); if (!this.anchor.getRefPt().isVerticalCenter()) { height -= 2 * this.anchor.getOffset().getDY(); } } Point2D pt = this.anchor.getAnchorPoint(target); double x = Double.NaN; if (this.anchor.getRefPt().isLeft()) { x = pt.getX(); } else if (this.anchor.getRefPt().isHorizontalCenter()) { x = target.getCenterX() - width / 2; } else if (this.anchor.getRefPt().isRight()) { x = pt.getX() - width; } double y = Double.NaN; if (this.anchor.getRefPt().isTop()) { y = pt.getY(); } else if (this.anchor.getRefPt().isVerticalCenter()) { y = target.getCenterY() - height / 2; } else if (this.anchor.getRefPt().isBottom()) { y = pt.getY() - height; } result.setRect(x, y, width, height); return result; } /** * Tests this instance for equality with an arbitrary object. * * @param obj the object ({@code null} permitted). * * @return A boolean. */ @Override public boolean equals(Object obj) { if (obj == this) { return true; } if (!(obj instanceof Fit2D)) { return false; } Fit2D that = (Fit2D) obj; if (!this.anchor.equals(that.anchor)) { return false; } if (!this.scale.equals(that.scale)) { return false; } return true; } } orson-charts-2.1.0/src/main/java/org/jfree/chart3d/graphics2d/RefPt2D.java000066400000000000000000000076441417331271500261200ustar00rootroot00000000000000/* =========================================================== * Orson Charts : a 3D chart library for the Java(tm) platform * =========================================================== * * (C)opyright 2013-2022, by David Gilbert. All rights reserved. * * https://github.com/jfree/orson-charts * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . * * [Oracle and Java are registered trademarks of Oracle and/or its affiliates. * Other names may be trademarks of their respective owners.] * * If you do not wish to be bound by the terms of the GPL, an alternative * commercial license can be purchased. For details, please see visit the * Orson Charts home page: * * http://www.object-refinery.com/orsoncharts/index.html * */ package org.jfree.chart3d.graphics2d; /** * An enumeration of reference points within a rectangle. These reference * points are used to place titles, legends and other labels. * * @see Anchor2D */ public enum RefPt2D { /** The top-left corner of a rectangle. */ TOP_LEFT, /** The middle of a rectangle at the top. */ TOP_CENTER, /** The top-right corner of a rectangle. */ TOP_RIGHT, /** The middle of a rectangle at the left side. */ CENTER_LEFT, /** The center of a rectangle. */ CENTER, /** The middle of a rectangle at the right side. */ CENTER_RIGHT, /** The bottom-left corner of a rectangle. */ BOTTOM_LEFT, /** The middle of a rectangle at the bottom. */ BOTTOM_CENTER, /** The bottom-right corner of a rectangle. */ BOTTOM_RIGHT; /** * Returns {@code true} if the reference point is at the left, and * {@code false} otherwise. * * @return A boolean. */ public boolean isLeft() { return (this == TOP_LEFT || this == CENTER_LEFT || this == BOTTOM_LEFT); } /** * Returns {@code true} if the reference point is at the right, and * {@code false} otherwise. * * @return A boolean. */ public boolean isRight() { return (this == TOP_RIGHT || this == CENTER_RIGHT || this == BOTTOM_RIGHT); } /** * Returns {@code true} if the reference point is at the center * horizontally, and {@code false} otherwise. * * @return A boolean. */ public boolean isHorizontalCenter() { return (this == TOP_CENTER || this == CENTER || this == BOTTOM_CENTER); } /** * Returns {@code true} if the reference point is at the top, and * {@code false} otherwise. * * @return A boolean. */ public boolean isTop() { return (this == TOP_LEFT || this == TOP_CENTER || this == TOP_RIGHT); } /** * Returns {@code true} if the reference point is at the bottom, and * {@code false} otherwise. * * @return A boolean. */ public boolean isBottom() { return (this == BOTTOM_LEFT || this == BOTTOM_CENTER || this == BOTTOM_RIGHT); } /** * Returns {@code true} if the reference point is at the center * vertically, and {@code false} otherwise. * * @return A boolean. */ public boolean isVerticalCenter() { return (this == CENTER_LEFT || this == CENTER || this == CENTER_RIGHT); } } orson-charts-2.1.0/src/main/java/org/jfree/chart3d/graphics2d/Scale2D.java000066400000000000000000000033101417331271500261110ustar00rootroot00000000000000/* =========================================================== * Orson Charts : a 3D chart library for the Java(tm) platform * =========================================================== * * (C)opyright 2013-2022, by David Gilbert. All rights reserved. * * https://github.com/jfree/orson-charts * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . * * [Oracle and Java are registered trademarks of Oracle and/or its affiliates. * Other names may be trademarks of their respective owners.] * * If you do not wish to be bound by the terms of the GPL, an alternative * commercial license can be purchased. For details, please see visit the * Orson Charts home page: * * http://www.object-refinery.com/orsoncharts/index.html * */ package org.jfree.chart3d.graphics2d; /** * Scaling options for fitting rectangles. */ public enum Scale2D { /** No scaling. */ NONE, /** Scale horizontally (but not vertically). */ SCALE_HORIZONTAL, /** Scale vertically (but not horizontally). */ SCALE_VERTICAL, /** Scale both horizontally and vertically. */ SCALE_BOTH } orson-charts-2.1.0/src/main/java/org/jfree/chart3d/graphics2d/TextAnchor.java000066400000000000000000000132371417331271500267640ustar00rootroot00000000000000/* =========================================================== * Orson Charts : a 3D chart library for the Java(tm) platform * =========================================================== * * (C)opyright 2013-2022, by David Gilbert. All rights reserved. * * https://github.com/jfree/orson-charts * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . * * [Oracle and Java are registered trademarks of Oracle and/or its affiliates. * Other names may be trademarks of their respective owners.] * * If you do not wish to be bound by the terms of the GPL, an alternative * commercial license can be purchased. For details, please see visit the * Orson Charts home page: * * http://www.object-refinery.com/orsoncharts/index.html * */ package org.jfree.chart3d.graphics2d; /** * Used to indicate the position of an anchor point for a text string. This is * frequently used to align a string to a fixed point in some coordinate space. */ public enum TextAnchor { /** Top/left. */ TOP_LEFT("TextAnchor.TOP_LEFT"), /** Top/center. */ TOP_CENTER("TextAnchor.TOP_CENTER"), /** Top/right. */ TOP_RIGHT("TextAnchor.TOP_RIGHT"), /** Half-ascent/left. */ HALF_ASCENT_LEFT("TextAnchor.HALF_ASCENT_LEFT"), /** Half-ascent/center. */ HALF_ASCENT_CENTER("TextAnchor.HALF_ASCENT_CENTER"), /** Half-ascent/right. */ HALF_ASCENT_RIGHT("TextAnchor.HALF_ASCENT_RIGHT"), /** Middle/left. */ CENTER_LEFT("TextAnchor.CENTER_LEFT"), /** Middle/center. */ CENTER("TextAnchor.CENTER"), /** Middle/right. */ CENTER_RIGHT("TextAnchor.CENTER_RIGHT"), /** Baseline/left. */ BASELINE_LEFT("TextAnchor.BASELINE_LEFT"), /** Baseline/center. */ BASELINE_CENTER("TextAnchor.BASELINE_CENTER"), /** Baseline/right. */ BASELINE_RIGHT("TextAnchor.BASELINE_RIGHT"), /** Bottom/left. */ BOTTOM_LEFT("TextAnchor.BOTTOM_LEFT"), /** Bottom/center. */ BOTTOM_CENTER("TextAnchor.BOTTOM_CENTER"), /** Bottom/right. */ BOTTOM_RIGHT("TextAnchor.BOTTOM_RIGHT"); /** The name. */ private final String name; /** * Private constructor. * * @param name the name. */ TextAnchor(String name) { this.name = name; } /** * Returns {@code true} if this anchor is at the left side of the * text bounds, and {@code false} otherwise. * * @return A boolean. */ public boolean isLeft() { return this == TOP_LEFT || this == CENTER_LEFT || this == HALF_ASCENT_LEFT || this == BASELINE_LEFT || this == BOTTOM_LEFT; } /** * Returns {@code true} if this anchor is horizontally at the center * of the text bounds, and {@code false} otherwise. * * @return A boolean. */ public boolean isHorizontalCenter() { return this == TOP_CENTER || this == CENTER || this == HALF_ASCENT_CENTER || this == BASELINE_CENTER || this == BOTTOM_CENTER; } /** * Returns {@code true} if this anchor is at the right side of the * text bounds, and {@code false} otherwise. * * @return A boolean. */ public boolean isRight() { return this == TOP_RIGHT || this == CENTER_RIGHT || this == HALF_ASCENT_RIGHT || this == BASELINE_RIGHT || this == BOTTOM_RIGHT; } /** * Returns {@code true} if this anchor is at the top of the * text bounds, and {@code false} otherwise. * * @return A boolean. */ public boolean isTop() { return this == TOP_LEFT || this == TOP_CENTER || this == TOP_RIGHT; } /** * Returns {@code true} if this anchor is at the half-ascent level of * the text bounds, and {@code false} otherwise. * * @return A boolean. */ public boolean isHalfAscent() { return this == HALF_ASCENT_LEFT || this == HALF_ASCENT_CENTER || this == HALF_ASCENT_RIGHT; } /** * Returns {@code true} if this anchor is at the half-height level of * the text bounds, and {@code false} otherwise. * * @return A boolean. */ public boolean isHalfHeight() { return this == CENTER_LEFT || this == CENTER || this == CENTER_RIGHT; } /** * Returns {@code true} if this anchor is at the baseline level of * the text bounds, and {@code false} otherwise. * * @return A boolean. */ public boolean isBaseline() { return this == BASELINE_LEFT || this == BASELINE_CENTER || this == BASELINE_RIGHT; } /** * Returns {@code true} if this anchor is at the bottom of * the text bounds, and {@code false} otherwise. * * @return A boolean. */ public boolean isBottom() { return this == BOTTOM_LEFT || this == BOTTOM_CENTER || this == BOTTOM_RIGHT; } /** * Returns a string representing the object. * * @return The string. */ @Override public String toString() { return this.name; } } orson-charts-2.1.0/src/main/java/org/jfree/chart3d/graphics2d/package-info.java000066400000000000000000000001311417331271500272160ustar00rootroot00000000000000/** * Utility classes related to 2D graphics. */ package org.jfree.chart3d.graphics2d; orson-charts-2.1.0/src/main/java/org/jfree/chart3d/graphics3d/000077500000000000000000000000001417331271500240355ustar00rootroot00000000000000orson-charts-2.1.0/src/main/java/org/jfree/chart3d/graphics3d/DefaultDrawable3D.java000066400000000000000000000164161417331271500301250ustar00rootroot00000000000000/* =========================================================== * Orson Charts : a 3D chart library for the Java(tm) platform * =========================================================== * * (C)opyright 2013-2022, by David Gilbert. All rights reserved. * * https://github.com/jfree/orson-charts * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . * * [Oracle and Java are registered trademarks of Oracle and/or its affiliates. * Other names may be trademarks of their respective owners.] * * If you do not wish to be bound by the terms of the GPL, an alternative * commercial license can be purchased. For details, please see visit the * Orson Charts home page: * * http://www.object-refinery.com/orsoncharts/index.html * */ package org.jfree.chart3d.graphics3d; import java.awt.BasicStroke; import java.awt.Color; import java.awt.Graphics2D; import java.awt.RenderingHints; import java.awt.geom.Rectangle2D; import java.awt.geom.AffineTransform; import java.awt.geom.GeneralPath; import java.awt.geom.Point2D; import java.util.ArrayList; import java.util.List; import org.jfree.chart3d.internal.Args; import org.jfree.chart3d.Chart3D; import org.jfree.chart3d.graphics3d.internal.Utils2D; import org.jfree.chart3d.graphics3d.internal.ZOrderComparator; /** * Provides a default implementation of the {@link Drawable3D} interface. * This is not used directly in Orson Charts, since the {@link Chart3D} class * implements the {@link Drawable3D} interface itself. However, it is used * in testing to ensure that the {@code org.jfree.chart3d.graphics3d} * package can function on a stand-alone basis. */ public class DefaultDrawable3D implements Drawable3D { /** * The default projection distance. * * @since 1.2 */ public static final double DEFAULT_PROJ_DIST = 1500.0; /** The viewing point. */ private ViewPoint3D viewPoint; /** The projection distance. */ private double projDist; /** The 3D world being drawn. */ private World world; private Offset2D offset; /** * Creates a new instance to display the content of the specified * {@code world}. * * @param world the world to view ({@code null} not permitted). */ public DefaultDrawable3D(World world) { Args.nullNotPermitted(world, "world"); this.viewPoint = new ViewPoint3D((float) (3 * Math.PI / 2.0), (float) Math.PI / 6, 40.0f, 0.0); this.projDist = DEFAULT_PROJ_DIST; this.world = world; this.offset = new Offset2D(); } /** * Returns the dimensions of the 3D object. * * @return The dimensions. */ @Override public Dimension3D getDimensions() { return new Dimension3D(1.0, 1.0, 1.0); // FIXME } /** * Returns the view point. * * @return The view point (never {@code null}). */ @Override public ViewPoint3D getViewPoint() { return this.viewPoint; } /** * Sets the view point. * * @param viewPoint the view point ({@code null} not permitted). */ @Override public void setViewPoint(ViewPoint3D viewPoint) { Args.nullNotPermitted(viewPoint, "viewPoint"); this.viewPoint = viewPoint; } /** * Returns the projection distance. The default value is * {@link #DEFAULT_PROJ_DIST}, higher numbers flatten out the perspective * and reduce distortion in the projected image. * * @return The projection distance. * * @since 1.2 */ @Override public double getProjDistance() { return this.projDist; } /** * Sets the projection distance. * * @param dist the distance. * * @since 1.2 */ @Override public void setProjDistance(double dist) { this.projDist = dist; } @Override public Offset2D getTranslate2D() { return this.offset; } @Override public void setTranslate2D(Offset2D offset) { Args.nullNotPermitted(offset, "offset"); this.offset = offset; } /** * Draws the current view to a {@code Graphics2D} instance. * * @param g2 the graphics target ({@code null} not permitted). * @param bounds the bounds ({@code null} not permitted). * * @return The rendering state. */ @Override public RenderingInfo draw(Graphics2D g2, Rectangle2D bounds) { Args.nullNotPermitted(g2, "g2"); g2.setStroke(new BasicStroke(1.0f, BasicStroke.CAP_ROUND, BasicStroke.JOIN_ROUND)); g2.setPaint(Color.WHITE); g2.fill(bounds); AffineTransform saved = g2.getTransform(); double dx = bounds.getWidth() / 2; double dy = bounds.getHeight() / 2; g2.translate(dx, dy); g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON); Point3D[] eyePts = this.world.calculateEyeCoordinates(this.viewPoint); Point2D[] pts = this.world.calculateProjectedPoints(this.viewPoint, this.projDist); List facesInPaintOrder = new ArrayList<>(this.world.getFaces()); // sort faces by z-order facesInPaintOrder.sort(new ZOrderComparator(eyePts)); for (Face f : facesInPaintOrder) { double[] plane = f.calculateNormal(eyePts); double inprod = plane[0] * this.world.getSunX() + plane[1] * this.world.getSunY() + plane[2] * this.world.getSunZ(); double shade = (inprod + 1) / 2.0; if (Utils2D.area2(pts[f.getVertexIndex(0)], pts[f.getVertexIndex(1)], pts[f.getVertexIndex(2)]) > 0) { Color c = f.getColor(); if (c != null) { GeneralPath p = new GeneralPath(); for (int v = 0; v < f.getVertexCount(); v++) { if (v == 0) { p.moveTo(pts[f.getVertexIndex(v)].getX(), pts[f.getVertexIndex(v)].getY()); } else { p.lineTo(pts[f.getVertexIndex(v)].getX(), pts[f.getVertexIndex(v)].getY()); } } p.closePath(); g2.setPaint(new Color((int) (c.getRed() * shade), (int) (c.getGreen() * shade), (int) (c.getBlue() * shade), c.getAlpha())); g2.fill(p); g2.draw(p); } } } g2.setTransform(saved); return new RenderingInfo(facesInPaintOrder, pts, dx, dy); } } orson-charts-2.1.0/src/main/java/org/jfree/chart3d/graphics3d/Dimension3D.java000066400000000000000000000114301417331271500270130ustar00rootroot00000000000000/* =========================================================== * Orson Charts : a 3D chart library for the Java(tm) platform * =========================================================== * * (C)opyright 2013-2022, by David Gilbert. All rights reserved. * * https://github.com/jfree/orson-charts * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . * * [Oracle and Java are registered trademarks of Oracle and/or its affiliates. * Other names may be trademarks of their respective owners.] * * If you do not wish to be bound by the terms of the GPL, an alternative * commercial license can be purchased. For details, please see visit the * Orson Charts home page: * * http://www.object-refinery.com/orsoncharts/index.html * */ package org.jfree.chart3d.graphics3d; import java.io.Serializable; /** * A dimension in 3D (width, height and depth). Instances of this class * are immutable. *

* NOTE: This class is serializable, but the serialization format is subject * to change in future releases and should not be relied upon for persisting * instances of this class. */ @SuppressWarnings("serial") public final class Dimension3D implements Serializable { /** The width. */ private final double width; /** The height. */ private final double height; /** The depth. */ private final double depth; /** * Creates a new {@code Dimension3D} instance. Instances of this * class are immutable. * * @param width the width. * @param height the height. * @param depth the depth. */ public Dimension3D(double width, double height, double depth) { this.width = width; this.height = height; this.depth = depth; } /** * Returns the width. * * @return The width. */ public double getWidth() { return this.width; } /** * Returns the height. * * @return The height. */ public double getHeight() { return this.height; } /** * Returns the depth. * * @return The depth. */ public double getDepth() { return this.depth; } /** * Returns the length of a diagonal from one corner of the box to another. * * @return The length. */ public double getDiagonalLength() { return Math.sqrt(this.depth * this.depth + this.height * this.height + this.width * this.width); } /** * Tests this instance for equality with an arbitrary object. * * @param obj the object to test against ({@code null} permitted). * * @return A boolean. */ @Override public boolean equals(Object obj) { if (obj == null) { return false; } if (getClass() != obj.getClass()) { return false; } final Dimension3D other = (Dimension3D) obj; if (Double.doubleToLongBits(this.width) != Double.doubleToLongBits( other.width)) { return false; } if (Double.doubleToLongBits(this.height) != Double.doubleToLongBits( other.height)) { return false; } if (Double.doubleToLongBits(this.depth) != Double.doubleToLongBits( other.depth)) { return false; } return true; } /** * Returns a hash code for this instance. * * @return A hash code. */ @Override public int hashCode() { int hash = 7; hash = 17 * hash + (int) (Double.doubleToLongBits(this.width) ^ (Double.doubleToLongBits(this.width) >>> 32)); hash = 17 * hash + (int) (Double.doubleToLongBits(this.height) ^ (Double.doubleToLongBits(this.height) >>> 32)); hash = 17 * hash + (int) (Double.doubleToLongBits(this.depth) ^ (Double.doubleToLongBits(this.depth) >>> 32)); return hash; } /** * Returns a string representation of this instance, primarily for * debugging purposes. * * @return A string. */ @Override public String toString() { return "[" + this.width + ", " + this.height + ", " + this.depth + "]"; } } orson-charts-2.1.0/src/main/java/org/jfree/chart3d/graphics3d/Dot3D.java000066400000000000000000000035371417331271500256250ustar00rootroot00000000000000/* =========================================================== * Orson Charts : a 3D chart library for the Java(tm) platform * =========================================================== * * (C)opyright 2013-2022, by David Gilbert. All rights reserved. * * https://github.com/jfree/orson-charts * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . * * [Oracle and Java are registered trademarks of Oracle and/or its affiliates. * Other names may be trademarks of their respective owners.] * * If you do not wish to be bound by the terms of the GPL, an alternative * commercial license can be purchased. For details, please see visit the * Orson Charts home page: * * http://www.object-refinery.com/orsoncharts/index.html * */ package org.jfree.chart3d.graphics3d; import java.awt.Color; /** * A 3D object that is simply a dot (single vertex). */ public class Dot3D extends Object3D { /** * Creates a new {@code Dot3D} instance. * * @param x the x-coordinate. * @param y the y-coordinate. * @param z the z-coordinate. * @param color the color ({@code null} not permitted). */ public Dot3D(float x, float y, float z, Color color) { super(color); addVertex(new Point3D(x, y, z)); } } orson-charts-2.1.0/src/main/java/org/jfree/chart3d/graphics3d/DoubleSidedFace.java000066400000000000000000000036421417331271500276470ustar00rootroot00000000000000/* =========================================================== * Orson Charts : a 3D chart library for the Java(tm) platform * =========================================================== * * (C)opyright 2013-2022, by David Gilbert. All rights reserved. * * https://github.com/jfree/orson-charts * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . * * [Oracle and Java are registered trademarks of Oracle and/or its affiliates. * Other names may be trademarks of their respective owners.] * * If you do not wish to be bound by the terms of the GPL, an alternative * commercial license can be purchased. For details, please see visit the * Orson Charts home page: * * http://www.object-refinery.com/orsoncharts/index.html * */ package org.jfree.chart3d.graphics3d; /** * A double-sided face. This is identical to a normal face except that during * rendering these faces will be drawn no matter which side they are viewed * from. * * @since 1.1 */ public class DoubleSidedFace extends Face { /** * Creates a new double-sided face. * * @param owner the object that the face belongs to ({@code null} not * permitted). * @param vertices the vertices. * * @since 1.3 */ public DoubleSidedFace(Object3D owner, int[] vertices) { super(owner, vertices); } } orson-charts-2.1.0/src/main/java/org/jfree/chart3d/graphics3d/Drawable3D.java000066400000000000000000000110771417331271500266160ustar00rootroot00000000000000/* =========================================================== * Orson Charts : a 3D chart library for the Java(tm) platform * =========================================================== * * (C)opyright 2013-2022, by David Gilbert. All rights reserved. * * https://github.com/jfree/orson-charts * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . * * [Oracle and Java are registered trademarks of Oracle and/or its affiliates. * Other names may be trademarks of their respective owners.] * * If you do not wish to be bound by the terms of the GPL, an alternative * commercial license can be purchased. For details, please see visit the * Orson Charts home page: * * http://www.object-refinery.com/orsoncharts/index.html * */ package org.jfree.chart3d.graphics3d; import java.awt.Graphics2D; import java.awt.geom.Rectangle2D; import org.jfree.chart3d.Chart3D; import org.jfree.chart3d.graphics3d.swing.Panel3D; /** * A three dimensional scene that can be viewed from an arbitrary viewpoint * and rendered to any {@link Graphics2D} instance. The {@link Chart3D} class * implements this interface. * * @see Panel3D */ public interface Drawable3D { /** * Returns the aggregate dimensions of the objects in the 3D scene. This * will be a bounding box for all the objects. One use for this * information is to determine a suitable default viewing distance for * a given scene (one that sizes the 2D projection to something appropriate * for the available drawing space). * * @return The dimensions (never {@code null}). */ Dimension3D getDimensions(); /** * Returns the point from which the 3D scene is viewed. The viewing point * determines how the 3D scene is projected onto the 2D viewing plane in * the {@link #draw(java.awt.Graphics2D, java.awt.geom.Rectangle2D)} method. * * @return The view point (never {@code null}). */ ViewPoint3D getViewPoint(); /** * Sets a new view point. Note that the {@code ViewPoint3D} class is * implemented so that its position and orientation can be updated directly, * so you should use this method only when you want to set an entirely * new view point. * * @param viewPoint the view point ({@code null} not permitted). */ void setViewPoint(ViewPoint3D viewPoint); /** * Returns the projection distance. A typical value is {@code 1500}, * higher numbers flatten out the perspective and reduce distortion in the * projected image. * * @return The projection distance. * * @since 1.2 */ double getProjDistance(); /** * Sets the projection distance. A typical value is {@code 1500} (but this * will depend on the dimensions of the scene), higher numbers flatten out * the perspective and reduce distortion in the projected image. * * @param dist the distance. * * @since 1.2 */ void setProjDistance(double dist); /** * Returns the 2D offset for the scene. Normally this will default * to {@code (0, 0)}. * * @return The translation offset (never {@code null}). */ Offset2D getTranslate2D(); /** * Sets the translation offset. This is typically used to allow the user * to modify the offset of a 2D projection on-screen by dragging with the * mouse. * * @param offset the translation offset ({@code null} not permitted). */ void setTranslate2D(Offset2D offset); /** * Draws the scene to the supplied {@code Graphics2D} target and returns * an object containing state information about the rendering. * * @param g2 the graphics target ({@code null} not permitted). * @param bounds the bounds ({@code null} not permitted). * * @return State information about the 3D scene that has been drawn * (never {@code null}). */ RenderingInfo draw(Graphics2D g2, Rectangle2D bounds); } orson-charts-2.1.0/src/main/java/org/jfree/chart3d/graphics3d/Face.java000066400000000000000000000204601417331271500255400ustar00rootroot00000000000000/* =========================================================== * Orson Charts : a 3D chart library for the Java(tm) platform * =========================================================== * * (C)opyright 2013-2022, by David Gilbert. All rights reserved. * * https://github.com/jfree/orson-charts * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . * * [Oracle and Java are registered trademarks of Oracle and/or its affiliates. * Other names may be trademarks of their respective owners.] * * If you do not wish to be bound by the terms of the GPL, an alternative * commercial license can be purchased. For details, please see visit the * Orson Charts home page: * * http://www.object-refinery.com/orsoncharts/index.html * */ package org.jfree.chart3d.graphics3d; import java.awt.Color; import java.awt.geom.Path2D; import java.awt.geom.Point2D; import org.jfree.chart3d.graphics3d.internal.TaggedFace; import org.jfree.chart3d.graphics3d.internal.Utils2D; import org.jfree.chart3d.internal.Args; /** * Represents a face in one {@link Object3D}, defined in terms of vertex * indices. It is expected (but not enforced) that all the vertices for * the face lie within a single plane. The face will be visible from the * "front" side only, which is a function of the order in which the vertices * are specified. A special subclass, {@link DoubleSidedFace}, is visible * from both front and back. */ public class Face { /** The object that the face belongs to. */ private Object3D owner; /** The offset into the global list of vertices. */ private int offset; /** * The indices of the vertices representing this face. Normally a face * should have at least three vertices (a triangle) but we allow a special * case with just two vertices to represent a line. */ private int[] vertices; /** * Creates a new face with the specified vertices that is part of the 3D * {@code owner} object. Most faces will have at least three vertices, * but a special case with just two vertices (representing a line) is * permitted. * * @param owner the object that owns the face ({@code null} not * permitted). * @param vertices the indices of the vertices (array length >= 2). * * @since 1.3 */ public Face(Object3D owner, int[] vertices) { if (vertices.length < 2) { throw new IllegalArgumentException( "Faces must have at least two vertices."); } Args.nullNotPermitted(owner, "owner"); this.owner = owner; this.vertices = vertices; this.offset = 0; } /** * Returns the object that this face belongs too (as passed to the * constructor). * * @return The owner (never {@code null}). * * @since 1.3 */ public Object3D getOwner() { return this.owner; } /** * Returns the offset to add to the vertex indices. * * @return The offset. */ public int getOffset() { return this.offset; } /** * Sets the offset to add to the vertex indices. * * @param offset the offset. */ public void setOffset(int offset) { this.offset = offset; } /** * Returns the number of vertices in this face. * * @return The number of vertices in this face. */ public int getVertexCount() { return this.vertices.length; } /** * Returns the index for the specified vertex. * * @param i the vertex index. * * @return The index. */ public int getVertexIndex(int i) { return this.vertices[i] + this.offset; } /** * A convenience method that looks up and returns the color for this face * (obtained by querying the object that owns the face). The color is * not stored as an attribute of the face, because typically an object * has many faces that are all the same color. * * @return The color (never {@code null}). */ public Color getColor() { return this.owner.getColor(this); } /** * Returns {@code true} if an outline should be drawn for this face, * and {@code false} otherwise. The value is obtained by querying * the object that owns the face. * * @return A boolean. */ public boolean getOutline() { return this.owner.getOutline(this); } /** * Returns the tag for this face (always {@code null} for this class, * subclasses may override). The {@link TaggedFace} class overrides * this method. * * @return {@code null}. * * @since 1.3 */ public String getTag() { return null; } /** * Calculates the normal vector for this face. * * @param points the vertices of the object that this face belongs to * (these can be in world or eye coordinates). * * @return The normal vector. */ public double[] calculateNormal(Point3D[] points) { int iA = this.vertices[0] + this.offset; int iB = this.vertices[1] + this.offset; int iC = this.vertices[2] + this.offset; double aX = points[iA].x; double aY = points[iA].y; double aZ = points[iA].z; double bX = points[iB].x; double bY = points[iB].y; double bZ = points[iB].z; double cX = points[iC].x; double cY = points[iC].y; double cZ = points[iC].z; double u1 = bX - aX, u2 = bY - aY, u3 = bZ - aZ; double v1 = cX - aX, v2 = cY - aY, v3 = cZ - aZ; double a = u2 * v3 - u3 * v2, b = u3 * v1 - u1 * v3, c = u1 * v2 - u2 * v1, len = Math.sqrt(a * a + b * b + c * c); a /= len; b /= len; c /= len; return new double[] {a, b, c}; } /** * Returns the average z-value. * * @param points the points. * * @return The average z-value. */ public float calculateAverageZValue(Point3D[] points) { float total = 0.0f; for (int i = 0; i < this.vertices.length; i++) { total = total + (float) points[this.vertices[i] + this.offset].z; } return total / this.vertices.length; } /** * Returns {@code true} if this face is front facing, and * {@code false} otherwise. * * @param projPts the projection points. * * @return A boolean. */ public boolean isFrontFacing(Point2D[] projPts) { return Utils2D.area2(projPts[getVertexIndex(0)], projPts[getVertexIndex(1)], projPts[getVertexIndex(2)]) > 0; } /** * Creates and returns a path for the outline of this face. * * @param pts the projected points for the world ({@code null} not * permitted). * * @return A path. * * @since 1.3 */ public Path2D createPath(Point2D[] pts) { Path2D path = new Path2D.Float(); for (int v = 0; v < getVertexCount(); v++) { Point2D pt = pts[getVertexIndex(v)]; if (v == 0) { path.moveTo(pt.getX(), pt.getY()); } else { path.lineTo(pt.getX(), pt.getY()); } } path.closePath(); return path; } /** * Returns a string representation of this instance, primarily for * debugging purposes. * * @return A string. */ @Override public String toString() { String result = "["; for (int i = 0; i < this.vertices.length; i++) { result = result + this.vertices[i]; if (i < this.vertices.length - 1) { result = result + ", "; } } return result + "]"; } } orson-charts-2.1.0/src/main/java/org/jfree/chart3d/graphics3d/LabelFace.java000066400000000000000000000115271417331271500265040ustar00rootroot00000000000000/* =========================================================== * Orson Charts : a 3D chart library for the Java(tm) platform * =========================================================== * * (C)opyright 2013-2022, by David Gilbert. All rights reserved. * * https://github.com/jfree/orson-charts * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . * * [Oracle and Java are registered trademarks of Oracle and/or its affiliates. * Other names may be trademarks of their respective owners.] * * If you do not wish to be bound by the terms of the GPL, an alternative * commercial license can be purchased. For details, please see visit the * Orson Charts home page: * * http://www.object-refinery.com/orsoncharts/index.html * */ package org.jfree.chart3d.graphics3d; import java.awt.Color; import java.awt.Font; import org.jfree.chart3d.internal.Args; /** * A face that carries a label (and is itself invisible). * * @since 1.3 */ public class LabelFace extends Face { /** A transparent color. */ private static final Color TRANSPARENT = new Color(0, 0, 0, 0); /** The label. */ private String label; /** The font for the label. */ private Font font; /** The foreground color for the text. */ private Color textColor; /** The background color. */ private Color backgroundColor; /** * Creates a new instance. * * @param owner the object that this face belongs to ({@code null} * not permitted). * @param vertices the vertices that define the face ({@code null} * not permitted). * @param label the label ({@code null} not permitted). * @param font the font ({@code null} not permitted). * @param textColor the foreground color ({@code null} not permitted). * @param backgroundColor the background color for the label * ({@code null} not permitted). */ public LabelFace(Object3D owner, int[] vertices, String label, Font font, Color textColor, Color backgroundColor) { super(owner, vertices); Args.nullNotPermitted(label, "label"); Args.nullNotPermitted(font, "font"); Args.nullNotPermitted(textColor, "textColor"); Args.nullNotPermitted(backgroundColor, "backgroundColor"); this.label = label; this.font = font; this.textColor = textColor; this.backgroundColor = backgroundColor; } /** * Returns a transparent color, so that the face is not visible. * * @return A transparent color. */ @Override public Color getColor() { return TRANSPARENT; } /** * Returns the label. * * @return The label (never {@code null}). */ public String getLabel() { return this.label; } /** * Sets the label. * * @param label the new label ({@code null} not permitted). */ public void setLabel(String label) { Args.nullNotPermitted(label, "label"); this.label = label; } /** * Returns the font. * * @return The font (never {@code null}). */ public Font getFont() { return this.font; } /** * Sets the font. * * @param font the font ({@code null} not permitted). */ public void setFont(Font font) { Args.nullNotPermitted(font, "font"); this.font = font; } /** * Returns the foreground color for the label text. * * @return The foreground color (never {@code null}). */ public Color getTextColor() { return this.textColor; } /** * Sets the foreground color for the label text. * * @param color the color ({@code null} not permitted). */ public void setTextColor(Color color) { this.textColor = color; } /** * Returns the background color. The default value is a fully transparent * color. * * @return The background color (never {@code null}). */ public Color getBackgroundColor() { return this.backgroundColor; } /** * Sets the background color. * * @param color the color ({@code null} not permitted). */ public void setBackgroundColor(Color color) { this.backgroundColor = color; } } orson-charts-2.1.0/src/main/java/org/jfree/chart3d/graphics3d/Line3D.java000066400000000000000000000260231417331271500257610ustar00rootroot00000000000000/* =========================================================== * Orson Charts : a 3D chart library for the Java(tm) platform * =========================================================== * * (C)opyright 2013-2022, by David Gilbert. All rights reserved. * * https://github.com/jfree/orson-charts * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . * * [Oracle and Java are registered trademarks of Oracle and/or its affiliates. * Other names may be trademarks of their respective owners.] * * If you do not wish to be bound by the terms of the GPL, an alternative * commercial license can be purchased. For details, please see visit the * Orson Charts home page: * * http://www.object-refinery.com/orsoncharts/index.html * */ package org.jfree.chart3d.graphics3d; import org.jfree.chart3d.internal.Args; /** * A line segment in 3D space. * * @since 1.5 */ public class Line3D { private Point3D start; private Point3D end; /** * Creates a new line in 3D space. * * @param start the starting point ({@code null} not permitted). * @param end the ending point ({@code null} not permitted). */ public Line3D(Point3D start, Point3D end) { Args.nullNotPermitted(start, "start"); Args.nullNotPermitted(end, "end"); this.start = start; this.end = end; } /** * Creates a new line in 3D space between the points {@code (x0, y0, z0)} * and {@code (x1, y1, z1)}. * * @param x0 the x-coordinate for the line's start point. * @param y0 the y-coordinate for the line's start point. * @param z0 the z-coordinate for the line's start point. * @param x1 the x-coordinate for the line's end point. * @param y1 the y-coordinate for the line's end point. * @param z1 the z-coordinate for the line's end point. */ public Line3D(double x0, double y0, double z0, double x1, double y1, double z1) { this.start = new Point3D(x0, y0, z0); this.end = new Point3D(x1, y1, z1); } /** * Returns the starting point for the line. * * @return The starting point (never {@code null}). */ public Point3D getStart() { return this.start; } /** * Returns the ending point for the line. * * @return The ending point (never {@code null}). */ public Point3D getEnd() { return this.end; } /** * Calculates and returns the line segment that is the result of cropping * the specified line segment to fit within an axis aligned bounding box. * * @param line the original line segment ({@code null} not permitted). * @param x0 the lower x-bound. * @param x1 the upper x-bound. * @param y0 the lower y-bound. * @param y1 the upper y-bound. * @param z0 the lower z-bound. * @param z1 the upper z-bound. * * @return The cropped line segment (or {@code null} if the original line * segment falls outside the bounding box). */ public static Line3D cropLineToAxisAlignedBoundingBox(Line3D line, double x0, double x1, double y0, double y1, double z0, double z1) { // we need this method to be fast, since it will get called a lot of // times during line chart rendering...there may be a faster method // than what is implemented below, in which case we should use it double xx0 = line.getStart().getX(); double xx1 = line.getEnd().getX(); int kx0 = 2; if (xx0 < x0) { kx0 = 1; } else if (xx0 > x1) { kx0 = 4; } int kx1 = 2; if (xx1 < x0) { kx1 = 1; } else if (xx1 > x1) { kx1 = 4; } if ((kx0 | kx1) == 1 || (kx0 | kx1) == 4) { return null; } double yy0 = line.getStart().getY(); double yy1 = line.getEnd().getY(); int ky0 = 2; if (yy0 < y0) { ky0 = 1; } else if (yy0 > y1) { ky0 = 4; } int ky1 = 2; if (yy1 < y0) { ky1 = 1; } else if (yy1 > y1) { ky1 = 4; } if ((ky0 | ky1) == 1 || (ky0 | ky1) == 4) { return null; } double zz0 = line.getStart().getZ(); double zz1 = line.getEnd().getZ(); int kz0 = 2; if (zz0 < z0) { kz0 = 1; } else if (zz0 > z1) { kz0 = 4; } int kz1 = 2; if (zz1 < z0) { kz1 = 1; } else if (zz1 > z1) { kz1 = 4; } if ((kz0 | kz1) == 1 || (kz0 | kz1) == 4) { return null; } // if the X's, Y's and Z's are all inside, just return the line if ((kx0 | kx1 | ky0 | ky1 | kz0 | kz1) == 2) { return line; } // now we know we have to do some clipping Point3D firstValidPoint = null; if (isPoint3DInBoundingBox(line.getStart(), x0, x1, y0, y1, z0, z1)) { firstValidPoint = line.getStart(); } if (isPoint3DInBoundingBox(line.getEnd(), x0, x1, y0, y1, z0, z1)) { firstValidPoint = line.getEnd(); } if (((kx0 | kx1) & 1) != 0) { // X's span the lower bound Point3D p = projectLineOnX(line, x0); if (isPoint3DInBoundingBox(p, x0, x1, y0, y1, z0, z1)) { if (firstValidPoint == null) { firstValidPoint = p; } else { return new Line3D(firstValidPoint, p); } } } if (((kx0 | kx1) & 4) != 0) { // X's span the upper bound Point3D p = projectLineOnX(line, x1); if (isPoint3DInBoundingBox(p, x0, x1, y0, y1, z0, z1)) { if (firstValidPoint == null) { firstValidPoint = p; } else { return new Line3D(firstValidPoint, p); } } } if (((ky0 | ky1) & 1) != 0) { // Y's span the lower bound Point3D p = projectLineOnY(line, y0); if (isPoint3DInBoundingBox(p, x0, x1, y0, y1, z0, z1)) { if (firstValidPoint == null) { firstValidPoint = p; } else { return new Line3D(firstValidPoint, p); } } } if (((ky0 | ky1) & 4) != 0) { // Y's span the upper bound Point3D p = projectLineOnY(line, y1); if (isPoint3DInBoundingBox(p, x0, x1, y0, y1, z0, z1)) { if (firstValidPoint == null) { firstValidPoint = p; } else { return new Line3D(firstValidPoint, p); } } } if (((kz0 | kz1) & 1) != 0) { // X's span the lower bound Point3D p = projectLineOnZ(line, z0); if (isPoint3DInBoundingBox(p, x0, x1, y0, y1, z0, z1)) { if (firstValidPoint == null) { firstValidPoint = p; } else { return new Line3D(firstValidPoint, p); } } } if (((kz0 | kz1) & 4) != 0) { // X's span the upper bound Point3D p = projectLineOnZ(line, z1); if (isPoint3DInBoundingBox(p, x0, x1, y0, y1, z0, z1)) { if (firstValidPoint == null) { firstValidPoint = p; } else { return new Line3D(firstValidPoint, p); } } } return null; } private static Point3D projectLineOnX(Line3D line, double x) { double x0 = line.getStart().getX(); double x1 = line.getEnd().getX(); double factor = 0.0; if (Math.abs(x1 - x0) > 0) { factor = (x - x0) / (x1 - x0); } if (factor >= 1.0) { return line.getEnd(); } else if (factor <= 0.0) { return line.getStart(); } else { double y0 = line.getStart().getY(); double y1 = line.getEnd().getY(); double z0 = line.getStart().getZ(); double z1 = line.getEnd().getZ(); return new Point3D(x0 + factor * (x1 - x0), y0 + factor * (y1 - y0), z0 + factor * (z1 - z0)); } } private static Point3D projectLineOnY(Line3D line, double y) { double y0 = line.getStart().getY(); double y1 = line.getEnd().getY(); double factor = 0.0; if (Math.abs(y1 - y0) > 0) { factor = (y - y0) / (y1 - y0); } if (factor >= 1.0) { return line.getEnd(); } else if (factor <= 0.0) { return line.getStart(); } else { double x0 = line.getStart().getX(); double x1 = line.getEnd().getX(); double z0 = line.getStart().getZ(); double z1 = line.getEnd().getZ(); return new Point3D(x0 + factor * (x1 - x0), y0 + factor * (y1 - y0), z0 + factor * (z1 - z0)); } } private static Point3D projectLineOnZ(Line3D line, double z) { double z0 = line.getStart().getZ(); double z1 = line.getEnd().getZ(); double factor = 0.0; if (Math.abs(z1 - z0) > 0) { factor = (z - z0) / (z1 - z0); } if (factor >= 1.0) { return line.getEnd(); } else if (factor <= 0.0) { return line.getStart(); } else { double x0 = line.getStart().getX(); double x1 = line.getEnd().getX(); double y0 = line.getStart().getY(); double y1 = line.getEnd().getY(); return new Point3D(x0 + factor * (x1 - x0), y0 + factor * (y1 - y0), z0 + factor * (z1 - z0)); } } private static boolean isPoint3DInBoundingBox(Point3D p, double x0, double x1, double y0, double y1, double z0, double z1) { double x = p.getX(); if (x < x0) { return false; } if (x > x1) { return false; } double y = p.getY(); if (y < y0) { return false; } if (y > y1) { return false; } double z = p.getZ(); if (z < z0) { return false; } if (z > z1) { return false; } return true; } } orson-charts-2.1.0/src/main/java/org/jfree/chart3d/graphics3d/LineObject3D.java000066400000000000000000000043541417331271500271130ustar00rootroot00000000000000/* =========================================================== * Orson Charts : a 3D chart library for the Java(tm) platform * =========================================================== * * (C)opyright 2013-2022, by David Gilbert. All rights reserved. * * https://github.com/jfree/orson-charts * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . * * [Oracle and Java are registered trademarks of Oracle and/or its affiliates. * Other names may be trademarks of their respective owners.] * * If you do not wish to be bound by the terms of the GPL, an alternative * commercial license can be purchased. For details, please see visit the * Orson Charts home page: * * http://www.object-refinery.com/orsoncharts/index.html * */ package org.jfree.chart3d.graphics3d; import java.awt.Color; /** * A line between two points in 3D space. * * @since 1.5 */ public class LineObject3D extends Object3D { /** * Creates a new {@code Line3D} instance. * * @param x0 the x-coordinate for the start of the line. * @param y0 the y-coordinate for the start of the line. * @param z0 the z-coordinate for the start of the line. * @param x1 the x-coordinate for the end of the line. * @param y1 the y-coordinate for the end of the line. * @param z1 the z-coordinate for the end of the line. * @param color the color ({@code null} not permitted). */ public LineObject3D(float x0, float y0, float z0, float x1, float y1, float z1, Color color) { super(color); addVertex(x0, y0, z0); addVertex(x1, y1, z1); addFace(new Face(this, new int[] {0, 1})); } } orson-charts-2.1.0/src/main/java/org/jfree/chart3d/graphics3d/Object3D.java000066400000000000000000000750731417331271500263110ustar00rootroot00000000000000/* =========================================================== * Orson Charts : a 3D chart library for the Java(tm) platform * =========================================================== * * (C)opyright 2013-2022, by David Gilbert. All rights reserved. * * https://github.com/jfree/orson-charts * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . * * [Oracle and Java are registered trademarks of Oracle and/or its affiliates. * Other names may be trademarks of their respective owners.] * * If you do not wish to be bound by the terms of the GPL, an alternative * commercial license can be purchased. For details, please see visit the * Orson Charts home page: * * http://www.object-refinery.com/orsoncharts/index.html * */ package org.jfree.chart3d.graphics3d; import java.awt.Color; import java.awt.Font; import java.awt.geom.Point2D; import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.Map; import org.jfree.chart3d.graphics3d.internal.TaggedFace; import org.jfree.chart3d.internal.Args; /** * An object defined in 3D space by (a) a list of coordinates, and (b) a list * of faces. This class has methods to calculate projected points in 2D when * a {@link ViewPoint3D} is provided. *

* This class also contains a collection of static methods for constructing * common 3D objects. */ public class Object3D { /** * The key for storing the object class as an optional property for this * object. * * @since 1.4 */ public static final String CLASS_KEY = "class"; /** * The key for storing item keys as property values. * * @since 1.3 */ public static final String ITEM_KEY = "key"; /** * A prefix used for setting color properties for an object. * * @since 1.3 */ public static final String COLOR_PREFIX = "color/"; /** World coordinates. */ private List vertices; /** Faces for the object, specified by indices to the world coords. */ private List faces; /** The primary color for the object. */ private Color color; /** * A flag that indicates whether or not faces for this object have their * outlines drawn (that is, the shape is filled then drawn versus just * filled only). */ private boolean outline; /** * A map containing properties for the object. If there are no properties * defined, then we leave this as {@code null} as an empty map would * consume memory unnecessarily. */ private Map properties; /** * Creates a new object, initially with no vertices or faces. * * @param color the default face color ({@code null} not permitted). * * @since 1.3 */ public Object3D(Color color) { this(color, false); } /** * Creates a new object, initially with no vertices or faces. * * @param color the default face color ({@code null} not permitted). * @param outline the default flag that determines whether face outlines * are drawn. * * @since 1.3 */ public Object3D(Color color, boolean outline) { Args.nullNotPermitted(color, "color"); this.color = color; this.outline = outline; this.vertices = new java.util.ArrayList<>(); this.faces = new java.util.ArrayList<>(); } /** * Returns the default face color as specified in the constructor. * * @return The color (never {@code null}). * * @since 1.3 */ public Color getColor() { return this.color; } /** * Returns the outline flag. * * @return The outline flag. * * @since 1.3 */ public boolean getOutline() { return this.outline; } /** * Sets the outline flag. This determines the default setting for whether * or not the faces of this object have their outlines drawn when rendered. * * @param outline the new flag value. * * @since 1.3 */ public void setOutline(boolean outline) { this.outline = outline; } /** * Returns the value of the property with the specified key, or * {@code null} if there is no property defined for that key. * * @param key the property key ({@code null} not permitted). * * @return The value (possibly {@code null}). * * @since 1.3 */ public Object getProperty(String key) { Args.nullNotPermitted(key, "key"); if (this.properties == null) { return null; } else { return this.properties.get(key); } } /** * Sets the value of a property, overwriting any existing value. One * application for this is storing item key references to link a 3D object * back to the data item that it represents (the key for this is * {@link Object3D#ITEM_KEY}). * * @param key the key ({@code null} not permitted). * @param value the value ({@code null} permitted). * * @since 1.3 */ public void setProperty(String key, Object value) { Args.nullNotPermitted(key, "key"); if (this.properties == null) { this.properties = new HashMap<>(); } this.properties.put(key, value); } /** * Returns the color for a specific face. If the face has a tag, then * this method will look for a property with the key COLOR_PREFIX + tag * and return that color, otherwise it returns the default color for the * object. * * @param face the face ({@code null} not permitted). * * @return The color for the specified face (never {@code null}). * * @since 1.3 */ public Color getColor(Face face) { if (face.getTag() != null) { // see if there is a custom color defined for the tag Object obj = getProperty(COLOR_PREFIX + face.getTag()); if (obj != null) { return (Color) obj; } } return this.color; } /** * Returns {@code true} if an outline should be drawn for the * specified face, and {@code false} otherwise. * * @param face the face ({@code null} not permitted). * * @return A boolean. * * @since 1.3 */ public boolean getOutline(Face face) { return this.outline; } /** * Returns the number of vertices for this object. * * @return The number of vertices. */ public int getVertexCount() { return this.vertices.size(); } /** * Adds a new object vertex with the specified coordinates. * * @param x the x-coordinate. * @param y the y-coordinate. * @param z the z-coordinate. */ public void addVertex(double x, double y, double z) { addVertex(new Point3D(x, y, z)); } /** * Adds a new object vertex. * * @param vertex the vertex ({@code null} not permitted). */ public void addVertex(Point3D vertex) { Args.nullNotPermitted(vertex, "vertex"); this.vertices.add(vertex); } /** * Returns the number of faces. * * @return The number of faces. */ public int getFaceCount() { return this.faces.size(); } /** * Adds a face for the given vertices (specified by index value). * * @param vertices the vertices (all should lie in a plane). * * @since 1.3 */ public void addFace(int[] vertices) { // defer the arg checks... addFace(new Face(this, vertices)); } /** * Adds a tagged face for the given vertices (specified by index value). * * @param vertices the vertices (all should lie in a plane). * @param tag the tag ({@code null} not permitted). * * @since 1.3 */ public void addFace(int[] vertices, String tag) { addFace(new TaggedFace(this, vertices, tag)); } /** * Adds a double-sided face for the given vertices (specified by index * value) and color. * * @param vertices the vertices (all should lie in a plane). * * @since 1.3 */ public void addDoubleSidedFace(int[] vertices) { addFace(new DoubleSidedFace(this, vertices)); } /** * Adds a face for this object. * * @param face the face ({@code null} not permitted). */ public void addFace(Face face) { Args.nullNotPermitted(face, "face"); this.faces.add(face); } /** * Returns the faces for this object. Note that the list returned is a * direct reference to the internal storage for this {@code Object3D} * instance, so callers should take care not to modify this list * unintentionally. * * @return The faces. */ public List getFaces() { return this.faces; } /** * Calculates the projected points for the object's vertices, for the * given viewpoint. * * @param viewPoint the view point ({@code null} not permitted). * @param d the projection distance. * * @return The projected points. */ public Point2D[] calculateProjectedPoints(ViewPoint3D viewPoint, double d) { Args.nullNotPermitted(viewPoint, "viewPoint"); Point2D[] result = new Point2D[this.vertices.size()]; int vertexCount = this.vertices.size(); for (int i = 0; i < vertexCount; i++) { Point3D p = this.vertices.get(i); result[i] = viewPoint.worldToScreen(p, d); } return result; } /** * Returns the eye coordinates of the object's vertices. * * @param viewPoint the view point ({@code null} not permitted). * * @return The eye coordinates. */ public Point3D[] calculateEyeCoordinates(ViewPoint3D viewPoint) { Args.nullNotPermitted(viewPoint, "viewPoint"); Point3D[] result = new Point3D[this.vertices.size()]; int i = 0; for (Point3D vertex : this.vertices) { result[i] = viewPoint.worldToEye(vertex); i++; } return result; } /** * Creates a square flat surface in the x-z plane (constant y) with a * single face. * * @param size the sheet size. * @param x the x-coordinate for the center of the square. * @param y the y-coordinate. * @param z the z-coordinate for the center of the square. * @param color the color ({@code null} not permitted). * @param invert invert the order of the face * * @return The sheet. */ public static Object3D createYSheet(double size, double x, double y, double z, Color color, boolean invert) { Args.nullNotPermitted(color, "color"); Object3D sheet = new Object3D(color); double delta = size / 2.0; sheet.addVertex(new Point3D(x + delta, y, z - delta)); sheet.addVertex(new Point3D(x + delta, y, z + delta)); sheet.addVertex(new Point3D(x - delta, y, z + delta)); sheet.addVertex(new Point3D(x - delta, y, z - delta)); if (invert) { sheet.addFace(new Face(sheet, new int[] {3, 2, 1, 0})); } else { sheet.addFace(new Face(sheet, new int[] {0, 1, 2, 3})); } return sheet; } /** * Creates a square flat surface in the x-y plane (constant z). * * @param size the sheet size. * @param x the x-coordinate of a point on the surface. * @param y the y-coordinate of a point on the surface. * @param z the z-coordinate of a point on the surface. * @param color the color. * * @return The sheet. */ public static Object3D createZSheet(double size, double x, double y, double z, Color color) { Object3D sheet = new Object3D(color); double delta = size / 2.0; sheet.addVertex(new Point3D(x + delta, y - delta, z)); sheet.addVertex(new Point3D(x + delta, y + delta, z)); sheet.addVertex(new Point3D(x - delta, y + delta, z)); sheet.addVertex(new Point3D(x - delta, y - delta, z)); sheet.addFace(new Face(sheet, new int[] {0, 1, 2, 3})); return sheet; } /** * Creates a cube centered on {@code (x, y, z)} with the specified * {@code size}. * * @param size the size. * @param x the x-offset. * @param y the y-offset. * @param z the z-offset. * @param color the color ({@code null} not permitted). * * @return The cube (never {@code null}). */ public static Object3D createCube(double size, double x, double y, double z, Color color) { return createBox(x, size, y, size, z, size, color); } /** * Creates a box centered on {@code (x, y, z)} with the specified * dimensions. * * @param x the x-coordinate. * @param xdim the length of the box in the x-dimension. * @param y the y-coordinate. * @param ydim the length of the box in the y-dimension. * @param z the z-coordinate. * @param zdim the length of the box in the y-dimension. * @param color the color ({@code null} not permitted). * * @return The box (never {@code null}). * * @see #createCube(double, double, double, double, java.awt.Color) */ public static Object3D createBox(double x, double xdim, double y, double ydim, double z, double zdim, Color color) { Args.nullNotPermitted(color, "color"); Object3D box = new Object3D(color); double xdelta = xdim / 2.0; double ydelta = ydim / 2.0; double zdelta = zdim / 2.0; box.addVertex(new Point3D(x - xdelta, y - ydelta, z - zdelta)); box.addVertex(new Point3D(x + xdelta, y - ydelta, z - zdelta)); box.addVertex(new Point3D(x + xdelta, y - ydelta, z + zdelta)); box.addVertex(new Point3D(x - xdelta, y - ydelta, z + zdelta)); box.addVertex(new Point3D(x - xdelta, y + ydelta, z - zdelta)); box.addVertex(new Point3D(x + xdelta, y + ydelta, z - zdelta)); box.addVertex(new Point3D(x + xdelta, y + ydelta, z + zdelta)); box.addVertex(new Point3D(x - xdelta, y + ydelta, z + zdelta)); box.addFace(new Face(box, new int[] {4, 5, 1, 0})); box.addFace(new Face(box, new int[] {5, 6, 2, 1})); box.addFace(new Face(box, new int[] {6, 7, 3, 2})); box.addFace(new Face(box, new int[] {3, 7, 4, 0})); box.addFace(new Face(box, new int[] {7, 6, 5, 4})); box.addFace(new Face(box, new int[] {0, 1, 2, 3})); return box; } /** * Creates a tetrahedron. * * @param size the size. * @param xOffset the x-offset. * @param yOffset the y-offset. * @param zOffset the z-offset. * @param color the color ({@code null} not permitted). * * @return A tetrahedron. */ public static Object3D createTetrahedron(double size, double xOffset, double yOffset, double zOffset, Color color) { Args.nullNotPermitted(color, "color"); Object3D tetra = new Object3D(color); tetra.addVertex(new Point3D(size + xOffset, -size + yOffset, -size + zOffset)); tetra.addVertex(new Point3D(-size + xOffset, size + yOffset, -size + zOffset)); tetra.addVertex(new Point3D(size + xOffset, size + yOffset, size + zOffset)); tetra.addVertex(new Point3D(-size + xOffset, -size + yOffset, size + zOffset)); tetra.addFace(new Face(tetra, new int[] {0, 1, 2})); tetra.addFace(new Face(tetra, new int[] {1, 3, 2})); tetra.addFace(new Face(tetra, new int[] {0, 3, 1})); tetra.addFace(new Face(tetra, new int[] {0, 2, 3})); return tetra; } /** * Creates an octahedron. * * @param size the size. * @param xOffset the x-offset. * @param yOffset the y-offset. * @param zOffset the z-offset. * @param color the color ({@code null} not permitted). * * @return An octahedron. */ public static Object3D createOctahedron(double size, double xOffset, double yOffset, double zOffset, Color color) { Args.nullNotPermitted(color, "color"); Object3D octa = new Object3D(color); octa.addVertex(new Point3D(size + xOffset, 0 + yOffset, 0 + zOffset)); octa.addVertex(new Point3D(0 + xOffset, size + yOffset, 0 + zOffset)); octa.addVertex(new Point3D(-size + xOffset, 0 + yOffset, 0 + zOffset)); octa.addVertex(new Point3D(0 + xOffset, -size + yOffset, 0 + zOffset)); octa.addVertex(new Point3D(0 + xOffset, 0 + yOffset, -size + zOffset)); octa.addVertex(new Point3D(0 + xOffset, 0 + yOffset, size + zOffset)); octa.addFace(new Face(octa, new int[] {0, 1, 5})); octa.addFace(new Face(octa, new int[] {1, 2, 5})); octa.addFace(new Face(octa, new int[] {2, 3, 5})); octa.addFace(new Face(octa, new int[] {3, 0, 5})); octa.addFace(new Face(octa, new int[] {1, 0, 4})); octa.addFace(new Face(octa, new int[] {2, 1, 4})); octa.addFace(new Face(octa, new int[] {3, 2, 4})); octa.addFace(new Face(octa, new int[] {0, 3, 4})); return octa; } /** * Creates an approximation of a sphere. * * @param radius the radius of the sphere (in world units). * @param n the number of layers. * @param x the x-coordinate of the center of the sphere. * @param y the y-coordinate of the center of the sphere. * @param z the z-coordinate of the center of the sphere. * @param extColor the exterior color ({@code null} not permitted). * @param intColor the interior color ({@code null} not permitted). * * @return A sphere. */ public static Object3D createSphere(double radius, int n, double x, double y, double z, Color extColor, Color intColor) { Object3D sphere = new Object3D(extColor); sphere.setProperty(COLOR_PREFIX + "interior", intColor); double theta = Math.PI / n; Point3D[] prevLayer = new Point3D[n * 2 + 1]; for (int i = 0; i <= n * 2; i++) { prevLayer[i] = new Point3D(x, y + radius, z); if (i != n * 2) { sphere.addVertex(prevLayer[i]); } } for (int layer = 1; layer < n; layer++) { Point3D[] currLayer = new Point3D[n * 2 + 1]; for (int i = 0; i <= n * 2; i++) { double xx = radius * Math.cos(i * theta) * Math.sin(layer * theta); double yy = radius * Math.cos(layer * theta); double zz = radius * Math.sin(i * theta) * Math.sin(layer * theta); currLayer[i] = new Point3D(x + xx, y + yy, z + zz); if (i != n * 2) { sphere.addVertex(currLayer[i]); } if (i > 0 && layer > 1) { if (i != n * 2) { Face f = new Face(sphere, new int[] { (layer - 1) * n * 2 + i - 1, (layer - 1) * n * 2 + i, layer * n * 2 + i, layer * n * 2 + i - 1}); sphere.addFace(f); f = new TaggedFace(sphere, new int[] { layer * n * 2 + i - 1, layer * n * 2 + i, (layer - 1) * n * 2 + i, (layer - 1) * n * 2 + i - 1}, "interior"); sphere.addFace(f); } else { sphere.addFace(new Face(sphere, new int[] { (layer - 1) * n * 2 + i - 1, (layer - 1) * n * 2, layer * n * 2, layer * n * 2 + i - 1})); sphere.addFace(new TaggedFace(sphere, new int[] { layer * n * 2 + i - 1, layer * n * 2, (layer - 1) * n * 2, (layer - 1) * n * 2 + i - 1}, "interior")); } } } } return sphere; } /** * Creates a pie segment with the specified attributes. * * @param radius the radius. * @param explodeRadius the explode radius (0.0 if not exploded). * @param base the base. * @param height the height. * @param angle1 the start angle (radians). * @param angle2 the end angle (radians). * @param inc the increment. * @param color the color ({@code null} not permitted). * * @return A pie segment object. */ public static Object3D createPieSegment(double radius, double explodeRadius, double base, double height, double angle1, double angle2, double inc, Color color) { Args.nullNotPermitted(color, "color"); Object3D segment = new Object3D(color, true); double angleCentre = (angle1 + angle2) / 2.0; Point3D centre = new Point3D(explodeRadius * Math.cos(angleCentre), base, explodeRadius * Math.sin(angleCentre)); float cx = (float) centre.x; float cz = (float) centre.z; segment.addVertex(new Point3D(cx + 0.0, base, cz + 0.0)); segment.addVertex(new Point3D(cx + 0.0, base + height, cz + 0.0)); Point3D v0 = new Point3D(cx + radius * Math.cos(angle1), base, cz + radius * Math.sin(angle1)); Point3D v1 = new Point3D(cx + radius * Math.cos(angle1), base + height, cz + radius * Math.sin(angle1)); segment.addVertex(v0); segment.addVertex(v1); segment.addFace(new Face(segment, new int[] {1, 3, 2, 0})); int vc = 4; // vertex count double theta = angle1 + inc; while (theta < angle2) { Point3D v2 = new Point3D(cx + radius * Math.cos(theta), base, cz + radius * Math.sin(theta)); Point3D v3 = new Point3D(cx + radius * Math.cos(theta), base + height, cz + radius * Math.sin(theta)); segment.addVertex(v2); segment.addVertex(v3); vc = vc + 2; // outside edge segment.addFace(new Face(segment, new int[] {vc - 2, vc - 4, vc - 3, vc - 1})); // top and bottom segment.addFace(new Face(segment, new int[] {0, vc - 4, vc - 2, 0})); segment.addFace(new Face(segment, new int[] {1, vc - 1, vc - 3, 1})); theta = theta + inc; } v0 = new Point3D(cx + radius * Math.cos(angle2), base, cz + radius * Math.sin(angle2)); v1 = new Point3D(cx + radius * Math.cos(angle2), base + height, cz + radius * Math.sin(angle2)); segment.addVertex(v0); segment.addVertex(v1); vc = vc + 2; segment.addFace(new Face(segment, new int[] {vc - 2, vc - 4, vc - 3, vc - 1})); // top and bottom segment.addFace(new Face(segment, new int[] {0, vc - 4, vc - 2, 0})); segment.addFace(new Face(segment, new int[] {1, vc - 1, vc - 3, 1})); // closing side segment.addFace(new Face(segment, new int[] {1, 0, vc-2, vc-1})); return segment; } /** * Returns two 3D objects (sheets in the y-plane) that can be used as * alignment anchors for the labels of a pie segment. One sheet is on the * front face of the segment, and the other is on the back face. Depending * on the viewing point, only one of the sheets will be showing, and this * is the one that the pie segment label will be attached to. * * @param radius the pie segment radius (in world units). * @param explodeRadius the pie segment explode radius (in world units). * @param base the base of the pie segment. * @param height the height of the pie segment. * @param angle1 the start angle of the segment (in radians). * @param angle2 the end angle of the segment (in radians). * * @return A list containing the two 3D objects to be used as pie label * markers. */ public static List createPieLabelMarkers(double radius, double explodeRadius, double base, double height, double angle1, double angle2) { List result = new ArrayList<>(); double angle = (angle1 + angle2) / 2.0; Point3D centre = new Point3D(explodeRadius * Math.cos(angle), base, explodeRadius * Math.sin(angle)); float cx = (float) centre.x; float cz = (float) centre.z; double r = radius * 0.9; Point3D v0 = new Point3D(cx + r * Math.cos(angle), base, cz + r * Math.sin(angle)); Point3D v1 = new Point3D(cx + r * Math.cos(angle), base + height, cz + r * Math.sin(angle)); result.add(Object3D.createYSheet(2.0, v0.x, v0.y, v0.z, Color.RED, false)); result.add(Object3D.createYSheet(2.0, v1.x, v1.y, v1.z, Color.BLUE, true)); return result; } /** * Creates a bar with the specified dimensions and color. * * @param xWidth the x-width of the bar. * @param zWidth the z-width (or depth) of the bar. * @param x the x-coordinate for the center of the bar. * @param y the y-coordinate for the top of the bar. * @param z the z-coordinate for the center of the bar. * @param zero the y-coordinate for the bottom of the bar. * @param barColor the color for the bar ({@code null} not permitted). * @param baseColor the color for the base of the bar (if {@code null}, * the {@code color} is used instead). * @param topColor the color for the top of the bar (if * {@code null}, the {@code color} is used instead). * @param inverted a flag that determines whether the baseColor and * topColor should be swapped in their usage. * * @return A 3D object that can represent a bar in a bar chart. */ public static Object3D createBar(double xWidth, double zWidth, double x, double y, double z, double zero, Color barColor, Color baseColor, Color topColor, boolean inverted) { Args.nullNotPermitted(barColor, "barColor"); Color c0 = baseColor; Color c1 = topColor; if (inverted) { Color cc = c1; c1 = c0; c0 = cc; } Object3D bar = new Object3D(barColor); if (c0 != null) { bar.setProperty(COLOR_PREFIX + "c0", c0); } if (c1 != null) { bar.setProperty(COLOR_PREFIX + "c1", c1); } double xdelta = xWidth / 2.0; double zdelta = zWidth / 2.0; bar.addVertex(new Point3D(x - xdelta, zero, z - zdelta)); bar.addVertex(new Point3D(x + xdelta, zero, z - zdelta)); bar.addVertex(new Point3D(x + xdelta, zero, z + zdelta)); bar.addVertex(new Point3D(x - xdelta, zero, z + zdelta)); bar.addVertex(new Point3D(x - xdelta, y, z - zdelta)); bar.addVertex(new Point3D(x + xdelta, y, z - zdelta)); bar.addVertex(new Point3D(x + xdelta, y, z + zdelta)); bar.addVertex(new Point3D(x - xdelta, y, z + zdelta)); bar.addFace(new Face(bar, new int[] {0, 1, 5, 4})); bar.addFace(new Face(bar, new int[] {4, 5, 1, 0})); bar.addFace(new Face(bar, new int[] {1, 2, 6, 5})); bar.addFace(new Face(bar, new int[] {5, 6, 2, 1})); bar.addFace(new Face(bar, new int[] {2, 3, 7, 6})); bar.addFace(new Face(bar, new int[] {6, 7, 3, 2})); bar.addFace(new Face(bar, new int[] {0, 4, 7, 3})); bar.addFace(new Face(bar, new int[] {3, 7, 4, 0})); bar.addFace(new Face(bar, new int[] {4, 5, 6, 7})); bar.addFace(new Face(bar, new int[] {3, 2, 1, 0})); if (c1 != null) { bar.addFace(new TaggedFace(bar, new int[] {7, 6, 5, 4}, "c1")); } else { bar.addFace(new Face(bar, new int[] {7, 6, 5, 4})); } if (c0 != null) { bar.addFace(new TaggedFace(bar, new int[] {0, 1, 2, 3}, "c0")); } else { bar.addFace(new Face(bar, new int[] {0, 1, 2, 3})); } return bar; } /** * Creates a label object, which has a single transparent face in the * Z-plane plus associated label attributes. These faces are used to * track the location and visibility of labels in a 3D scene. * * @param label the label ({@code null} not permitted). * @param font the font ({@code null} not permitted). * @param fgColor the label foreground color ({@code null} not permitted). * @param bgColor the label background color ({@code null} not permitted). * @param x the x-coordinate in 3D space. * @param y the y-coordinate in 3D space. * @param z the z-coordinate in 3D space. * @param reversed reverse the order of the vertices? * @param doubleSided is the face double-sided (visible from either side)? * * @return A new label object (never {@code null}). * * @since 1.3 */ public static Object3D createLabelObject(String label, Font font, Color fgColor, Color bgColor, double x, double y, double z, boolean reversed, boolean doubleSided) { Object3D labelObj = new Object3D(bgColor); labelObj.setProperty(Object3D.CLASS_KEY, "ItemLabel"); labelObj.addVertex(x - 0.1, y, z); labelObj.addVertex(x + 0.1, y, z); labelObj.addVertex(x + 0.1, y + 0.1, z); labelObj.addVertex(x - 0.1, y + 0.1, z); if (!reversed || doubleSided) { labelObj.addFace(new LabelFace(labelObj, new int[] {0, 1, 2, 3}, label, font, fgColor, bgColor)); } if (reversed || doubleSided) { labelObj.addFace(new LabelFace(labelObj, new int[] {3, 2, 1, 0}, label, font, fgColor, bgColor)); } return labelObj; } } orson-charts-2.1.0/src/main/java/org/jfree/chart3d/graphics3d/Offset2D.java000066400000000000000000000071361417331271500263230ustar00rootroot00000000000000/* =========================================================== * Orson Charts : a 3D chart library for the Java(tm) platform * =========================================================== * * (C)opyright 2013-2022, by David Gilbert. All rights reserved. * * https://github.com/jfree/orson-charts * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . * * [Oracle and Java are registered trademarks of Oracle and/or its affiliates. * Other names may be trademarks of their respective owners.] * * If you do not wish to be bound by the terms of the GPL, an alternative * commercial license can be purchased. For details, please see visit the * Orson Charts home page: * * http://www.object-refinery.com/orsoncharts/index.html * */ package org.jfree.chart3d.graphics3d; import java.io.Serializable; /** * An offset {@code (dx, dy)} in two dimensional space. Instances of * this class are immutable. *

* NOTE: This class is serializable, but the serialization format is subject * to change in future releases and should not be relied upon for persisting * instances of this class. */ @SuppressWarnings("serial") public final class Offset2D implements Serializable { /** Zero offset. */ public static final Offset2D ZERO_OFFSET = new Offset2D(0, 0); /** The x-offset. */ private double dx; /** The y-offset. */ private double dy; /** * Default constructor ({@code (0, 0)}). */ public Offset2D() { this(0.0, 0.0); } /** * Creates a new instance. * * @param dx the x-offset. * @param dy the y-offset. */ public Offset2D(double dx, double dy) { this.dx = dx; this.dy = dy; } /** * Returns the x-offset. * * @return The x-offset. */ public double getDX() { return this.dx; } /** * Returns the y-offset. * * @return The y-offset. */ public double getDY() { return this.dy; } /** * Tests this instance for equality with an arbitrary object. * * @param obj the object ({@code null} permitted). * * @return A boolean. */ @Override public boolean equals(Object obj) { if (obj == this) { return true; } if (!(obj instanceof Offset2D)) { return false; } Offset2D that = (Offset2D) obj; if (this.dx != that.dx) { return false; } if (this.dy != that.dy) { return false; } return true; } /** * Returns a hash code for this instance. * * @return A hash code. */ @Override public int hashCode() { int hash = 3; hash = 59 * hash + (int) (Double.doubleToLongBits(this.dx) ^ (Double.doubleToLongBits(this.dx) >>> 32)); hash = 59 * hash + (int) (Double.doubleToLongBits(this.dy) ^ (Double.doubleToLongBits(this.dy) >>> 32)); return hash; } } orson-charts-2.1.0/src/main/java/org/jfree/chart3d/graphics3d/Offset3D.java000066400000000000000000000101511417331271500263130ustar00rootroot00000000000000/* =========================================================== * Orson Charts : a 3D chart library for the Java(tm) platform * =========================================================== * * (C)opyright 2013-2022, by David Gilbert. All rights reserved. * * https://github.com/jfree/orson-charts * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . * * [Oracle and Java are registered trademarks of Oracle and/or its affiliates. * Other names may be trademarks of their respective owners.] * * If you do not wish to be bound by the terms of the GPL, an alternative * commercial license can be purchased. For details, please see visit the * Orson Charts home page: * * http://www.object-refinery.com/orsoncharts/index.html * */ package org.jfree.chart3d.graphics3d; import java.io.Serializable; /** * An offset {@code (dx, dy, dz)} in three dimensional space. Instances * of this class are immutable. *

* NOTE: This class is serializable, but the serialization format is subject * to change in future releases and should not be relied upon for persisting * instances of this class. * * @since 1.3 */ @SuppressWarnings("serial") public final class Offset3D implements Serializable { /** Zero offset. */ public static final Offset3D ZERO_OFFSET = new Offset3D(0, 0, 0); /** The x-offset. */ private double dx; /** The y-offset. */ private double dy; /** The z-offset. */ private double dz; /** * Default constructor ({@code (0, 0)}). */ public Offset3D() { this(0.0, 0.0, 0.0); } /** * Creates a new instance. * * @param dx the x-offset. * @param dy the y-offset. * @param dz the z-offset. */ public Offset3D(double dx, double dy, double dz) { this.dx = dx; this.dy = dy; this.dz = dz; } /** * Returns the x-offset. * * @return The x-offset. */ public double getDX() { return this.dx; } /** * Returns the y-offset. * * @return The y-offset. */ public double getDY() { return this.dy; } /** * Returns the z-offset. * * @return The z-offset. */ public double getDZ() { return this.dz; } /** * Tests this instance for equality with an arbitrary object. * * @param obj the object ({@code null} permitted). * * @return A boolean. */ @Override public boolean equals(Object obj) { if (obj == this) { return true; } if (!(obj instanceof Offset3D)) { return false; } Offset3D that = (Offset3D) obj; if (this.dx != that.dx) { return false; } if (this.dy != that.dy) { return false; } if (this.dz != that.dz) { return false; } return true; } @Override public int hashCode() { int hash = 7; hash = 97 * hash + (int) (Double.doubleToLongBits(this.dx) ^ (Double.doubleToLongBits(this.dx) >>> 32)); hash = 97 * hash + (int) (Double.doubleToLongBits(this.dy) ^ (Double.doubleToLongBits(this.dy) >>> 32)); hash = 97 * hash + (int) (Double.doubleToLongBits(this.dz) ^ (Double.doubleToLongBits(this.dz) >>> 32)); return hash; } @Override public String toString() { return "[" + this.dx + ", " + this.dy + ", " + this.dz + "]"; } } orson-charts-2.1.0/src/main/java/org/jfree/chart3d/graphics3d/Point3D.java000066400000000000000000000132611417331271500261630ustar00rootroot00000000000000/* =========================================================== * Orson Charts : a 3D chart library for the Java(tm) platform * =========================================================== * * (C)opyright 2013-2022, by David Gilbert. All rights reserved. * * https://github.com/jfree/orson-charts * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . * * [Oracle and Java are registered trademarks of Oracle and/or its affiliates. * Other names may be trademarks of their respective owners.] * * If you do not wish to be bound by the terms of the GPL, an alternative * commercial license can be purchased. For details, please see visit the * Orson Charts home page: * * http://www.object-refinery.com/orsoncharts/index.html * */ package org.jfree.chart3d.graphics3d; import java.io.Serializable; /** * A point in 3D space (this class is also used to represent vectors in 3D * space). Instances of this class are immutable. *

* NOTE: This class is serializable, but the serialization format is subject * to change in future releases and should not be relied upon for persisting * instances of this class. */ @SuppressWarnings("serial") public final class Point3D implements Serializable { /** The origin {@code (0, 0, 0)}. */ public static final Point3D ORIGIN = new Point3D(0, 0, 0); /** The point {@code (1, 0, 0)}. */ public static final Point3D UNIT_X = new Point3D(1, 0, 0); /** The point {@code (0, 1, 0)}. */ public static final Point3D UNIT_Y = new Point3D(0, 1, 0); /** The point {@code (0, 0, 1)}. */ public static final Point3D UNIT_Z = new Point3D(0, 0, 1); /** The x-coordinate. */ public double x; /** The y-coordinate. */ public double y; /** The z-coordinate. */ public double z; /** * Creates a new {@code Point3D} instance from spherical coordinates. * * @param theta theta (in radians). * @param phi phi (in radians). * @param rho the distance from the origin. * * @return The point (never {@code null}). */ public static Point3D createPoint3D(double theta, double phi, double rho) { double x = rho * Math.sin(phi) * Math.cos(theta); double y = rho * Math.sin(phi) * Math.sin(theta); double z = rho * Math.cos(phi); return new Point3D(x, y, z); } /** * Creates a new point in 3D space. * * @param x the x-coordinate. * @param y the y-coordinate. * @param z the z-coordinate. */ public Point3D(double x, double y, double z) { this.x = x; this.y = y; this.z = z; } /** * Returns the x-coordinate specified in the constructor. * * @return The x-coordinate. */ public double getX() { return this.x; } /** * Returns the y-coordinate specified in the constructor. * * @return The y-coordinate. */ public double getY() { return this.y; } /** * Returns the z-coordinate specified in the constructor. * * @return The z-coordinate. */ public double getZ() { return this.z; } /** * Returns theta (calculated from the cartesian coordinates). * * @return Theta. */ public double getTheta() { return Math.atan2(y, x); } /** * Returns phi (calculated from the cartesian coordinates). * * @return phi. */ public double getPhi() { return Math.acos(z / getRho()); } /** * Returns rho (calculated from the cartesian coordinates). * * @return rho. */ public double getRho() { return Math.sqrt(x * x + y * y + z * z); } /** * Tests this instance for equality to an arbitrary object. * * @param obj the object ({@code null} permitted). * * @return A boolean. */ @Override public boolean equals(Object obj) { if (obj == this) { return true; } if (!(obj instanceof Point3D)) { return false; } Point3D that = (Point3D) obj; if (this.x != that.x) { return false; } if (this.y != that.y) { return false; } if (this.z != that.z) { return false; } return true; } @Override public int hashCode() { int hash = 7; hash = 29 * hash + (int) (Double.doubleToLongBits(this.x) ^ (Double.doubleToLongBits(this.x) >>> 32)); hash = 29 * hash + (int) (Double.doubleToLongBits(this.y) ^ (Double.doubleToLongBits(this.y) >>> 32)); hash = 29 * hash + (int) (Double.doubleToLongBits(this.z) ^ (Double.doubleToLongBits(this.z) >>> 32)); return hash; } /** * Returns a string representation of this instance, primarily for * debugging purposes. * * @return A string (never {@code null}). */ @Override public String toString() { return "[" + this.x + ", " + this.y + ", " + this.z + "]"; } } orson-charts-2.1.0/src/main/java/org/jfree/chart3d/graphics3d/RenderedElement.java000066400000000000000000000076261417331271500277550ustar00rootroot00000000000000/* =========================================================== * Orson Charts : a 3D chart library for the Java(tm) platform * =========================================================== * * (C)opyright 2013-2022, by David Gilbert. All rights reserved. * * https://github.com/jfree/orson-charts * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . * * [Oracle and Java are registered trademarks of Oracle and/or its affiliates. * Other names may be trademarks of their respective owners.] * * If you do not wish to be bound by the terms of the GPL, an alternative * commercial license can be purchased. For details, please see visit the * Orson Charts home page: * * http://www.object-refinery.com/orsoncharts/index.html * */ package org.jfree.chart3d.graphics3d; import java.awt.Shape; import java.util.HashMap; import java.util.Map; import org.jfree.chart3d.internal.Args; /** * Represents an item or element that has been rendered by the graphics engine. * Properties can be assigned to the elements in order to provide the * information required for such things as end user interactivity. * * @since 1.3 */ public class RenderedElement { /** A key for the 'type' property. The value is an Object. */ public static final String TYPE = "type"; /** * A key for the 'bounds' property (the value is a {@code Shape}). */ public static final String BOUNDS = "bounds"; /** Properties for the element. */ private final Map properties; /** * Creates a new interactive element with the specified type. * * @param type the type ({@code null} not permitted). * @param bounds the bounds ({@code null} permitted). */ public RenderedElement(Object type, Shape bounds) { Args.nullNotPermitted(type, "type"); this.properties = new HashMap<>(); this.properties.put(TYPE, type); this.properties.put(RenderedElement.BOUNDS, bounds); } /** * Returns the element type, as specified in the constructor. * * @return The element type. */ public Object getType() { return this.properties.get(TYPE); } /** * Returns the value of the property with the specified key, or * {@code null}). * * @param key the key ({@code null} not permitted). * * @return The property value. */ public Object getProperty(String key) { return this.properties.get(key); } /** * Sets the value for a property. * * @param key the property key ({@code null} not permitted). * @param value the property value. */ public void setProperty(String key, Object value) { this.properties.put(key, value); } /** * Clears all properties for this element. */ public void clearProperties() { this.properties.clear(); } /** * Returns a string representation of the element, primarily for * debugging purposes. * * @return A string. */ @Override public String toString() { StringBuilder sb = new StringBuilder(); Object type = this.properties.get(TYPE); sb.append("RenderedElement[").append(type).append(",") .append(this.properties.entrySet()).append("]"); return sb.toString(); } } orson-charts-2.1.0/src/main/java/org/jfree/chart3d/graphics3d/RenderingInfo.java000066400000000000000000000161551417331271500274410ustar00rootroot00000000000000/* =========================================================== * Orson Charts : a 3D chart library for the Java(tm) platform * =========================================================== * * (C)opyright 2013-2022, by David Gilbert. All rights reserved. * * https://github.com/jfree/orson-charts * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . * * [Oracle and Java are registered trademarks of Oracle and/or its affiliates. * Other names may be trademarks of their respective owners.] * * If you do not wish to be bound by the terms of the GPL, an alternative * commercial license can be purchased. For details, please see visit the * Orson Charts home page: * * http://www.object-refinery.com/orsoncharts/index.html * */ package org.jfree.chart3d.graphics3d; import java.awt.Shape; import java.awt.geom.Path2D; import java.awt.geom.Point2D; import java.awt.geom.Rectangle2D; import java.util.List; import java.util.ArrayList; /** * Rendering info returned from the {@link Drawable3D} {@code draw()} * method. * * @since 1.3 */ public class RenderingInfo { /** * A list of the faces drawn in order of rendering. */ private final List faces; /** The projected points for the vertices in the faces. */ Point2D[] projPts; /** The x-translation. */ private final double dx; /** The y-translation. */ public double dy; /** * Storage for rendered elements in the model other than the 3D objects * (caters for code that overlays other items such as labels). */ List otherElements; List otherOffsetElements; /** * Creates a new instance. * * @param faces the rendered faces (in order of rendering). * @param projPts the projected points for all vertices in the 3D model. * @param dx the x-delta. * @param dy the y-delta. */ public RenderingInfo(List faces, Point2D[] projPts, double dx, double dy) { this.faces = faces; this.projPts = projPts; this.dx = dx; this.dy = dy; this.otherElements = new ArrayList<>(); this.otherOffsetElements = new ArrayList<>(); } /** * Returns the list of faces rendered. * * @return The list of faces. */ public List getFaces() { return this.faces; } /** * Returns the projected points. * * @return The projected points. */ public Point2D[] getProjectedPoints() { return this.projPts; } /** * Returns the x-translation amount. All projected points are centered * on (0, 0) but the rendering to the screen (or other Graphics2D target) * performs two translations: the first is to the center of the bounding * rectangle, and the second is to apply the translate2D attribute of the * chart. The result of these translations is stored here and used in the * fetchObjectAt(x, y) method. * * @return The x-translation. */ public double getDX() { return this.dx; } /** * Returns the y-translation amount. * * @return The y-translation. */ public double getDY() { return this.dy; } /** * Adds a rendered element to the rendering info. * * @param element the element ({@code null} not permitted). */ public void addElement(RenderedElement element) { this.otherElements.add(element); } /** * Adds a rendered element to the list of offset elements. * * @param element the element ({@code null} not permitted). */ public void addOffsetElement(RenderedElement element) { this.otherOffsetElements.add(element); } /** * Fetches the object, if any, that is rendered at {@code (x, y)}. * * @param x the x-coordinate. * @param y the y-coordinate. * * @return The object (or {@code null}). */ public Object3D fetchObjectAt(double x, double y) { for (int i = this.faces.size() - 1; i >= 0; i--) { Face f = this.faces.get(i); if (f instanceof LabelFace) { Rectangle2D bounds = (Rectangle2D) f.getOwner().getProperty("labelBounds"); if (bounds != null && bounds.contains(x - dx, y - dy)) { return f.getOwner(); } } else { Path2D p = f.createPath(this.projPts); if (p.contains(x - dx, y - dy)) { return f.getOwner(); } } } return null; } /** * Finds the rendered element, if any, at the location {@code (x, y)}. * The method first calls fetchObjectAt(x, y) to see if there is an * object at the specified location and, if there is, returns a new * RenderedElement instance for that object. Otherwise, it searches the * otherElements list to see if there is some other element (such as a * title, legend, axis label or axis tick label) and returns that item. * Finally, if no element is found, the method returns {@code null}. * * @param x the x-coordinate. * @param y the y-coordinate. * * @return The interactive element or {@code null}. */ public RenderedElement findElementAt(double x, double y) { for (int i = this.otherElements.size() - 1; i >= 0; i--) { RenderedElement element = this.otherElements.get(i); Shape bounds = (Shape) element.getProperty(RenderedElement.BOUNDS); if (bounds.contains(x, y)) { return element; } } for (int i = this.otherOffsetElements.size() - 1; i >= 0; i--) { RenderedElement element = this.otherOffsetElements.get(i); Shape bounds = (Shape) element.getProperty(RenderedElement.BOUNDS); if (bounds != null && bounds.contains(x - dx, y - dy)) { return element; } } Object3D obj = fetchObjectAt(x, y); if (obj != null) { RenderedElement element = new RenderedElement("obj3d", null); element.setProperty(Object3D.ITEM_KEY, obj.getProperty(Object3D.ITEM_KEY)); if (obj.getProperty(Object3D.CLASS_KEY) != null) { element.setProperty(Object3D.CLASS_KEY, obj.getProperty(Object3D.CLASS_KEY)); } return element; } return null; } } orson-charts-2.1.0/src/main/java/org/jfree/chart3d/graphics3d/Rotate3D.java000066400000000000000000000175001417331271500263300ustar00rootroot00000000000000/* =========================================================== * Orson Charts : a 3D chart library for the Java(tm) platform * =========================================================== * * (C)opyright 2013-2022, by David Gilbert. All rights reserved. * * https://github.com/jfree/orson-charts * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . * * [Oracle and Java are registered trademarks of Oracle and/or its affiliates. * Other names may be trademarks of their respective owners.] * * If you do not wish to be bound by the terms of the GPL, an alternative * commercial license can be purchased. For details, please see visit the * Orson Charts home page: * * http://www.object-refinery.com/orsoncharts/index.html * */ package org.jfree.chart3d.graphics3d; import java.io.Serializable; /** * Performs rotations about along an arbitrary axis (defined by two * {@link Point3D} instances). This file is derived from code published in * "Computer Graphics for Java Programmers (Second Edition)" by Leen Ammeraal * and Kang Zhang. *

* NOTE: This class is serializable, but the serialization format is subject * to change in future releases and should not be relied upon for persisting * instances of this class. */ @SuppressWarnings("serial") public class Rotate3D implements Serializable { /** The first point defining the axis of rotation. */ Point3D a; /** The second point defining the axis of rotation. */ Point3D b; /** The angle of rotation in radians. */ double angle; /** * Values in the transformation matrix (these need to be recalculated if * the axis of rotation or the angle are changed). */ double r11, r12, r13; double r21, r22, r23; double r31, r32, r33; double r41, r42, r43; /** * Creates a new instance that will rotate points about the axis passing * through points a and b, by the specified angle. * * @param a the first point defining the axis of rotation * ({@code null} not permitted). * @param b the second point defining the axis of rotation * ({@code null} not permitted). * @param angle the rotation angle (in radians). */ public Rotate3D(Point3D a, Point3D b, double angle) { this.a = a; this.b = b; this.angle = angle; double v1 = b.x - a.x; double v2 = b.y - a.y; double v3 = b.z - a.z; double theta = Math.atan2(v2, v1); double phi = Math.atan2(Math.sqrt(v1 * v1 + v2 * v2), v3); initRotate(a, theta, phi, angle); } /** * Returns the angle of rotation, in radians. * * @return The angle of rotation, in radians. */ public double getAngle() { return this.angle; } /** * Sets the angle of rotation (in radians) and (internally) updates the * values of the transformation matrix ready for the next call(s) to * the {@code applyRotation} methods. * * @param angle the angle (in radians). */ public void setAngle(double angle) { this.angle = angle; double v1 = b.x - a.x; double v2 = b.y - a.y; double v3 = b.z - a.z; double theta = Math.atan2(v2, v1); double phi = Math.atan2(Math.sqrt(v1 * v1 + v2 * v2), v3); initRotate(this.a, theta, phi, angle); } /** * Computes the transformation matrix values. * * @param a the start point of the axis of rotation. * @param theta theta (defines direction of axis). * @param phi phi (defines direction of axis). * @param alpha alpha (angle of rotation). */ private void initRotate(Point3D a, double theta, double phi, double alpha) { double cosAlpha = Math.cos(alpha); double sinAlpha = Math.sin(alpha); double cosPhi = Math.cos(phi); double cosPhi2 = cosPhi * cosPhi; double sinPhi = Math.sin(phi); double sinPhi2 = sinPhi * sinPhi; double cosTheta = Math.cos(theta); double cosTheta2 = cosTheta * cosTheta; double sinTheta = Math.sin(theta); double sinTheta2 = sinTheta * sinTheta; double a1 = a.x; double a2 = a.y; double a3 = a.z; double c = 1.0 - cosAlpha; this.r11 = cosTheta2 * (cosAlpha * cosPhi2 + sinPhi2) + cosAlpha * sinTheta2; this.r12 = sinAlpha * cosPhi + c * sinPhi2 * cosTheta * sinTheta; this.r13 = sinPhi * (cosPhi * cosTheta * c - sinAlpha * sinTheta); this.r21 = sinPhi2 * cosTheta * sinTheta * c - sinAlpha * cosPhi; this.r22 = sinTheta2 * (cosAlpha * cosPhi2 + sinPhi2) + cosAlpha * cosTheta2; this.r23 = sinPhi * (cosPhi * sinTheta * c + sinAlpha * cosTheta); this.r31 = sinPhi * (cosPhi * cosTheta * c + sinAlpha * sinTheta); this.r32 = sinPhi * (cosPhi * sinTheta * c - sinAlpha * cosTheta); this.r33 = cosAlpha * sinPhi2 + cosPhi2; this.r41 = a1 - a1 * this.r11 - a2 * this.r21 - a3 * this.r31; this.r42 = a2 - a1 * this.r12 - a2 * this.r22 - a3 * this.r32; this.r43 = a3 - a1 * this.r13 - a2 * this.r23 - a3 * this.r33; } /** * Creates and returns a new point that is the rotation of {@code p} * about the axis that was specified via the constructor. * * @param p the point ({@code null} not permitted). * * @return A new point. */ public Point3D applyRotation(Point3D p) { return applyRotation(p.x, p.y, p.z); } /** * Creates an returns a new point that is the rotation of the point * {@code (x, y, z)} about the axis that was specified via the * constructor. * * @param x the x-coordinate of the point to transform. * @param y the y-coordinate of the point to transform. * @param z the z-coordinate of the point to transform. * * @return The transformed point (never {@code null}). */ public Point3D applyRotation(double x, double y, double z) { return new Point3D( x * this.r11 + y * this.r21 + z * this.r31 + this.r41, x * this.r12 + y * this.r22 + z * this.r32 + this.r42, x * this.r13 + y * this.r23 + z * this.r33 + this.r43); } /** * Returns the coordinates of a point that is the rotation of the point * {@code (x, y, z)} about the axis that was specified via the * constructor. * * @param x the x-coordinate of the point to transform. * @param y the y-coordinate of the point to transform. * @param z the z-coordinate of the point to transform. * @param result an array to carry the result ({@code null} permitted). * * @return The transformed coordinates (in the {@code result} array if * one was supplied, otherwise in a newly allocated array). */ public double[] applyRotation(double x, double y, double z, double[] result) { if (result == null) { result = new double[3]; } result[0] = x * this.r11 + y * this.r21 + z * this.r31 + this.r41; result[1] = x * this.r12 + y * this.r22 + z * this.r32 + this.r42; result[2] = x * this.r13 + y * this.r23 + z * this.r33 + this.r43; return result; } } orson-charts-2.1.0/src/main/java/org/jfree/chart3d/graphics3d/ViewPoint3D.java000066400000000000000000000435131417331271500270210ustar00rootroot00000000000000/* =========================================================== * Orson Charts : a 3D chart library for the Java(tm) platform * =========================================================== * * (C)opyright 2013-2022, by David Gilbert. All rights reserved. * * https://github.com/jfree/orson-charts * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . * * [Oracle and Java are registered trademarks of Oracle and/or its affiliates. * Other names may be trademarks of their respective owners.] * * If you do not wish to be bound by the terms of the GPL, an alternative * commercial license can be purchased. For details, please see visit the * Orson Charts home page: * * http://www.object-refinery.com/orsoncharts/index.html * */ package org.jfree.chart3d.graphics3d; import java.awt.Color; import java.awt.Dimension; import java.awt.geom.Dimension2D; import java.awt.geom.Point2D; import java.io.Serializable; import org.jfree.chart3d.graphics3d.internal.Utils2D; import org.jfree.chart3d.graphics3d.internal.Utils3D; /** * Specifies the location and orientation of the view point in 3D space. * Assumes the eye looks towards the origin in world coordinates. *

* There are four basic operations to move the view point: *

    *
  • {@link #panLeftRight(double)} - rotates around the scene horizontally * from the perspective of the viewer;
  • *
  • {@link #moveUpDown(double)} - rotates around the scene vertically from * the perspective of the viewer;
  • *
  • {@link #roll(double)} - maintains the same viewing location but rolls * by the specified angle (like tilting a camera);
  • *
  • {@link #setRho(double)} - sets the distance of the view location from * the center of the 3D scene (zoom in and out).
  • *
*

* NOTE: This class is serializable, but the serialization format is subject * to change in future releases and should not be relied upon for persisting * instances of this class. */ @SuppressWarnings("serial") public class ViewPoint3D implements Serializable { /** * Creates and returns a view point for looking at a chart from the * front and above. * * @param rho the distance. * * @return A view point. */ public static ViewPoint3D createAboveViewPoint(double rho) { return new ViewPoint3D(-Math.PI / 2, 9 * Math.PI / 8, rho, 0); } /** * Creates and returns a view point for looking at a chart from the * front and above and to the left. * * @param rho the distance. * * @return A view point. */ public static ViewPoint3D createAboveLeftViewPoint(double rho) { ViewPoint3D vp = createAboveViewPoint(rho); vp.panLeftRight(-Math.PI / 6); return vp; } /** * Creates and returns a view point for looking at a chart from the * front and above and to the right. * * @param rho the distance. * * @return A view point. */ public static ViewPoint3D createAboveRightViewPoint(double rho) { ViewPoint3D vp = createAboveViewPoint(rho); vp.panLeftRight(Math.PI / 6); return vp; } /** The rotation of the viewing point from the x-axis around the z-axis. */ private double theta; /** The rotation (up and down) of the viewing point. */ private double phi; /** The distance of the viewing point from the origin. */ private double rho; /** Transformation matrix elements. */ private double v11, v12, v13, v21, v22, v23, v32, v33, v43; /** * A point 1/4 turn "upwards" on the sphere, to define the camera * orientation. */ private Point3D up; /** Applies the rotation for the orientation of the view. */ private Rotate3D rotation; /** A workspace for calling the Rotate3D class. */ private double[] workspace; /** * Creates a new viewing point. * * @param theta the rotation of the viewing point from the x-axis around * the z-axis (in radians) * @param phi the rotation of the viewing point up and down (from the * XZ plane, in radians) * @param rho the distance of the viewing point from the origin. * @param orientation the angle of rotation. */ public ViewPoint3D(double theta, double phi, double rho, double orientation) { this.theta = theta; this.phi = phi; this.rho = rho; updateMatrixElements(); this.rotation = new Rotate3D(Point3D.ORIGIN, Point3D.UNIT_Z, orientation); this.up = this.rotation.applyRotation(Point3D.createPoint3D(this.theta, this.phi - Math.PI / 2, this.rho)); this.workspace = new double[3]; } /** * Creates a new instance using the specified point and orientation. * * @param p the viewing point. * @param orientation the orientation. */ public ViewPoint3D(Point3D p, double orientation) { this.rho = (float) Math.sqrt(p.x * p.x + p.y * p.y + p.z * p.z); if (Math.sqrt(p.x * p.x + p.y * p.y) > 0.000001) { this.theta = (float) Math.atan2(p.y, p.x); } this.phi = (float) Math.acos(p.z / this.rho); updateMatrixElements(); this.rotation = new Rotate3D( Point3D.ORIGIN, Point3D.UNIT_Z, orientation); this.up = this.rotation.applyRotation(Point3D.createPoint3D(this.theta, this.phi - Math.PI / 2, this.rho)); this.workspace = new double[3]; } /** * Creates a new instance that is an exact copy of the supplied viewpoint. * * @param vp the view point ({@code null} not permitted). * * @since 1.6.1 */ public ViewPoint3D(ViewPoint3D vp) { this.theta = vp.theta; this.phi = vp.phi; this.rho = vp.rho; updateMatrixElements(); this.rotation = new Rotate3D(Point3D.ORIGIN, Point3D.UNIT_Z, vp.rotation.angle); this.up = vp.up; this.workspace = new double[3]; } /** * Returns the angle of rotation from the x-axis about the z-axis, * in radians. This attribute is set via the constructor and updated * via the {@link #panLeftRight(double)} and {@link #moveUpDown(double)} * methods - there is no setter method, you cannot update it directly. * * @return The angle (in radians). */ public final double getTheta() { return this.theta; } /** * Returns the angle of the viewing point down from the z-axis. This * attribute is set via the constructor and updated via the * {@link #panLeftRight(double)} and {@link #moveUpDown(double)} methods * - there is no setter method, you cannot update it directly. * * @return The angle of the viewing point down from the z-axis. * (in radians). */ public final double getPhi() { return this.phi; } /** * Returns the distance of the viewing point from the origin. * * @return The distance of the viewing point from the origin. * * @see #setRho(double) */ public final double getRho() { return this.rho; } /** * Sets the distance of the viewing point from the origin. * * @param rho the new distance. */ public void setRho(double rho) { this.rho = rho; this.up = Point3D.createPoint3D(this.up.getTheta(), this.up.getPhi(), rho); updateMatrixElements(); } /** * Returns the x-coordinate of the viewing point. This value is * calculated from the spherical coordinates. * * @return The x-coordinate of the viewing point. */ public final double getX() { return this.rho * Math.sin(this.phi) * Math.cos(this.theta); } /** * Returns the y-coordinate of the viewing point. This value is * calculated from the spherical coordinates. * * @return The y-coordinate of the viewing point. */ public final double getY() { return this.rho * Math.sin(this.phi) * Math.sin(this.theta); } /** * Returns the z-coordinate of the viewing point. This value is * calculated from the spherical coordinates. * * @return The z-coordinate of the viewing point. */ public final double getZ() { return this.rho * Math.cos(this.phi); } /** * Returns the location of the view point. Note that a new instance of * {@code Point3D} is created each time this method is called. * * @return The viewing point (never {@code null}). */ public final Point3D getPoint() { return new Point3D(getX(), getY(), getZ()); } /** * Returns the roll angle (orientation) for the view point. This is * calculated by reference to second point on the sphere that is a * quarter turn from the view point location (this second point defines * the "up" direction for the view). * * @return The roll angle (in radians). */ public double calcRollAngle() { Point3D vp = getPoint(); Point3D n1 = Utils3D.normal(vp, this.up, Point3D.ORIGIN); Point3D screenup = Point3D.createPoint3D(this.theta, this.phi - (Math.PI / 2), this.rho); Point3D n2 = Utils3D.normal(vp, screenup, Point3D.ORIGIN); double angle = Utils3D.angle(n1, n2); if (Utils3D.scalarprod(n1, screenup) >= 0.0) { return angle; } else { return -angle; } } /** * Moves the viewing point left or right around the 3D scene. * * @param delta the angle (in radians). */ public void panLeftRight(double delta) { Point3D v = getVerticalRotationAxis(); Rotate3D r = new Rotate3D(Point3D.ORIGIN, v, delta); Point3D p = r.applyRotation(getX(), getY(), getZ()); this.theta = p.getTheta(); this.phi = p.getPhi(); updateMatrixElements(); this.rotation.setAngle(calcRollAngle()); } /** * Moves the viewing point up or down on the viewing sphere. * * @param delta the angle delta (in radians). */ public void moveUpDown(double delta) { Point3D v = getHorizontalRotationAxis(); Rotate3D r = new Rotate3D(Point3D.ORIGIN, v, delta); Point3D p = r.applyRotation(getX(), getY(), getZ()); this.up = r.applyRotation(this.up); this.theta = p.getTheta(); this.phi = p.getPhi(); updateMatrixElements(); this.rotation.setAngle(calcRollAngle()); } /** * Rolls the view while leaving the location of the view point unchanged. * * @param delta the angle (in radians). */ public void roll(double delta) { // we rotate the "up" point around the sphere by delta radians Rotate3D r = new Rotate3D(getPoint(), Point3D.ORIGIN, delta); this.up = r.applyRotation(this.up); this.rotation.setAngle(calcRollAngle()); } /** * Converts a point in world coordinates to a point in eye coordinates. * * @param p the point ({@code null} not permitted). * * @return The point in eye coordinates. */ public Point3D worldToEye(Point3D p) { double x = this.v11 * p.x + this.v21 * p.y; double y = this.v12 * p.x + this.v22 * p.y + this.v32 * p.z; double z = this.v13 * p.x + this.v23 * p.y + this.v33 * p.z + this.v43; double[] rotated = this.rotation.applyRotation(x, y, z, this.workspace); return new Point3D(rotated[0], rotated[1], rotated[2]); } /** * Calculates and returns the screen coordinates for the specified point * in (world) 3D space. * * @param p the point. * @param d the projection distance. * * @return The screen coordinate. */ public Point2D worldToScreen(Point3D p, double d) { double x = this.v11 * p.x + this.v21 * p.y; double y = this.v12 * p.x + this.v22 * p.y + this.v32 * p.z; double z = this.v13 * p.x + this.v23 * p.y + this.v33 * p.z + this.v43; double[] rotated = this.rotation.applyRotation(x, y, z, this.workspace); return new Point2D.Double(-d * rotated[0] / rotated[2], -d * rotated[1] / rotated[2]); } /** * Calculate the distance that would render a box of the given dimensions * within a screen area of the specified size. * * @param target the target dimension ({@code null} not permitted). * @param dim3D the dimensions of the 3D content ({@code null} not * permitted). * @param projDist the projection distance. * * @return The optimal viewing distance. */ public float optimalDistance(Dimension2D target, Dimension3D dim3D, double projDist) { ViewPoint3D vp = new ViewPoint3D(this.theta, this.phi, this.rho, calcRollAngle()); float near = (float) dim3D.getDiagonalLength(); float far = near * 40; World w = new World(); double ww = dim3D.getWidth(); double hh = dim3D.getHeight(); double dd = dim3D.getDepth(); w.add(Object3D.createBox(0, ww, 0, hh, 0, dd, Color.RED)); while (true) { vp.setRho(near); Point2D[] nearpts = w.calculateProjectedPoints(vp, projDist); Dimension neardim = Utils2D.findDimension(nearpts); double nearcover = coverage(neardim, target); vp.setRho(far); Point2D[] farpts = w.calculateProjectedPoints(vp, projDist); Dimension fardim = Utils2D.findDimension(farpts); double farcover = coverage(fardim, target); if (nearcover <= 1.0) { return near; } if (farcover >= 1.0) { return far; } // bisect near and far until we get close enough to the specified // dimension float mid = (near + far) / 2.0f; vp.setRho(mid); Point2D[] midpts = w.calculateProjectedPoints(vp, projDist); Dimension middim = Utils2D.findDimension(midpts); double midcover = coverage(middim, target); if (midcover >= 1.0) { near = mid; } else { far = mid; } } } private double coverage(Dimension2D d, Dimension2D target) { double wpercent = d.getWidth() / target.getWidth(); double hpercent = d.getHeight() / target.getHeight(); if (wpercent <= 1.0 && hpercent <= 1.0) { return Math.max(wpercent, hpercent); } else { if (wpercent >= 1.0) { if (hpercent >= 1.0) { return Math.max(wpercent, hpercent); } else { return wpercent; } } else { return hpercent; // don't think it will matter } } } /** * Updates the matrix elements. */ private void updateMatrixElements() { float cosTheta = (float) Math.cos(this.theta); float sinTheta = (float) Math.sin(this.theta); float cosPhi = (float) Math.cos(this.phi); float sinPhi = (float) Math.sin(this.phi); this.v11 = -sinTheta; this.v12 = -cosPhi * cosTheta; this.v13 = sinPhi * cosTheta; this.v21 = cosTheta; this.v22 = -cosPhi * sinTheta; this.v23 = sinPhi * sinTheta; this.v32 = sinPhi; this.v33 = cosPhi; this.v43 = -this.rho; } /** * Returns the vector that points "up" in relation to the orientation of * the view point. This vector can be used to rotate the viewing point * around the 3D scene (pan left / right). * * @return The vector (never {@code null}). */ public Point3D getVerticalRotationAxis() { return this.up; } /** * Returns a vector at right angles to the viewing direction and the "up" * vector (this axis can be used to rotate forward and backwards). * * @return A vector (never {@code null}). */ public Point3D getHorizontalRotationAxis() { return Utils3D.normal(getPoint(), this.up, Point3D.ORIGIN); } /** * Returns a string representation of this instance, primarily for * debugging purposes. * * @return A string. */ @Override public String toString() { return "[theta=" + this.theta + ", phi=" + this.phi + ", rho=" + this.rho + "]"; } /** * Tests this view point for equality with an arbitrary object. * * @param obj the object ({@code null} permitted). * * @return A boolean. */ @Override public boolean equals(Object obj) { if (obj == this) { return true; } if (!(obj instanceof ViewPoint3D)) { return false; } ViewPoint3D that = (ViewPoint3D) obj; if (this.theta != that.theta) { return false; } if (this.phi != that.phi) { return false; } if (this.rho != that.rho) { return false; } if (!this.up.equals(that.up)) { return false; } return true; } } orson-charts-2.1.0/src/main/java/org/jfree/chart3d/graphics3d/World.java000066400000000000000000000216301417331271500257710ustar00rootroot00000000000000/* =========================================================== * Orson Charts : a 3D chart library for the Java(tm) platform * =========================================================== * * (C)opyright 2013-2022, by David Gilbert. All rights reserved. * * https://github.com/jfree/orson-charts * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . * * [Oracle and Java are registered trademarks of Oracle and/or its affiliates. * Other names may be trademarks of their respective owners.] * * If you do not wish to be bound by the terms of the GPL, an alternative * commercial license can be purchased. For details, please see visit the * Orson Charts home page: * * http://www.object-refinery.com/orsoncharts/index.html * */ package org.jfree.chart3d.graphics3d; import java.awt.geom.Point2D; import java.util.ArrayList; import java.util.Collection; import java.util.List; import java.util.Map; import java.util.Map.Entry; import org.jfree.chart3d.graphics3d.internal.Utils3D; import org.jfree.chart3d.internal.Args; /** * A world is a model containing a collection of objects in 3D space and a * direction vector for the sunlight. A viewing point ({@link ViewPoint3D}) is * specified externally. Objects in the world are assigned to a partition, * providing the ability to group objects. */ public class World { /** * The default partition key. All objects in the world are added with * a partition key. There always exists at least one partition (the * default partition). * * @since 1.2 */ public static final String DEFAULT_PARTITION_KEY = "default"; /** The sunlight vector. */ private double sunX; private double sunY; private double sunZ; /** * Storage for the objects in the world. A map is used to store * one or more lists of objects (the partitioning is useful so * that updates can be made to subsets of the world). */ private Map> objects; /** * Creates a new empty world. */ public World() { this.objects = new java.util.TreeMap<>(); this.objects.put(DEFAULT_PARTITION_KEY, new ArrayList<>()); setSunSource(new Point3D(2, -1, 10)); } /** * Returns the x-component of the sunlight vector. * * @return The x-component of the sunlight vector. */ public double getSunX() { return this.sunX; } /** * Returns the y-component of the sunlight vector. * * @return The y-component of the sunlight vector. */ public double getSunY() { return this.sunY; } /** * Returns the z-component of the sunlight vector. * * @return The z-component of the sunlight vector. */ public double getSunZ() { return this.sunZ; } /** * Sets the light source point. * * @param x the x-coordinate. * @param y the y-coordinate. * @param z the z-coordinate. * * @since 1.2 */ public final void setSunSource(double x, double y, double z) { setSunSource(new Point3D(x, y, z)); } /** * Sets the light source point. * * @param p the point ({@code null} not permitted). * * @since 1.2 */ public final void setSunSource(Point3D p) { Args.nullNotPermitted(p, "p"); Point3D normal = Utils3D.normalise(p); this.sunX = normal.getX(); this.sunY = normal.getY(); this.sunZ = normal.getZ(); } /** * Adds an object to the world in the default partition. * * @param object the object ({@code null} not permitted). */ public void add(Object3D object) { // defer argument checking add(DEFAULT_PARTITION_KEY, object); } /** * Adds an object to a specific partition. * * @param partition the partition ({@code null} not permitted). * @param object the object ({@code null} not permitted). * * @since 1.2 */ public void add(String partition, Object3D object) { Args.nullNotPermitted(partition, "partition"); Args.nullNotPermitted(object, "object"); List list = this.objects.get(partition); if (list == null) { list = new ArrayList<>(); this.objects.put(partition, list); } list.add(object); } /** * Adds a collection of objects to the world (in the default * partition). * * @param objects the objects ({@code null} not permitted). */ public void addAll(Collection objects) { Args.nullNotPermitted(objects, "objects"); for (Object3D object : objects) { add(object); } } /** * Clears any objects belonging to the specified partition. * * @param partitionKey the partition key ({@code null} not permitted). * * @since 1.2 */ public void clear(String partitionKey) { Args.nullNotPermitted(partitionKey, "partitionKey"); this.objects.put(partitionKey, null); } /** * Returns the total number of vertices for all objects in this world. * * @return The total number of vertices. */ public int getVertexCount() { int count = 0; for (Entry> entry : this.objects.entrySet()) { List objs = entry.getValue(); for (Object3D object: objs) { count += object.getVertexCount(); } } return count; } /** * Returns an array containing the vertices for all objects in this * world, transformed to eye coordinates. * * @param vp the view point ({@code null} not permitted). * * @return The eye coordinates. */ public Point3D[] calculateEyeCoordinates(ViewPoint3D vp) { Point3D[] result = new Point3D[getVertexCount()]; int index = 0; for (Entry> entry : this.objects.entrySet()) { List objs = entry.getValue(); for (Object3D object : objs) { Point3D[] vertices = object.calculateEyeCoordinates(vp); System.arraycopy(vertices, 0, result, index, vertices.length); index = index + vertices.length; } } return result; } /** * Calculates the projected points in 2D-space for all the vertices of the * objects in the world. * * @param vp the view point ({@code null} not permitted). * @param d the distance. * * @return The projected points. */ public Point2D[] calculateProjectedPoints(ViewPoint3D vp, double d) { Point2D[] result = new Point2D[getVertexCount()]; int index = 0; for (Entry> entry : this.objects.entrySet()) { List objs = entry.getValue(); for (Object3D object : objs) { Point2D[] pts = object.calculateProjectedPoints(vp, d); System.arraycopy(pts, 0, result, index, pts.length); index = index + pts.length; } } return result; } /** * Fetches the faces for all the objects in this world, updating the * offset to match the current position. * * @return A list of faces. */ public List getFaces() { List result = new java.util.ArrayList<>(); int offset = 0; for (Entry> entry : this.objects.entrySet()) { List objs = entry.getValue(); for (Object3D object : objs) { for (Face f : object.getFaces()) { f.setOffset(offset); } offset += object.getVertexCount(); result.addAll(object.getFaces()); } } return result; } /** * Returns a newly created list containing all the objects in the world * model. * * @return The list of objects. * * @since 1.2 */ public List getObjects() { List result = new ArrayList<>(); for (Entry> entry : this.objects.entrySet()) { List objs = entry.getValue(); result.addAll(objs); } return result; } } orson-charts-2.1.0/src/main/java/org/jfree/chart3d/graphics3d/internal/000077500000000000000000000000001417331271500256515ustar00rootroot00000000000000orson-charts-2.1.0/src/main/java/org/jfree/chart3d/graphics3d/internal/FaceSorter.java000066400000000000000000000041351417331271500305540ustar00rootroot00000000000000/* =========================================================== * Orson Charts : a 3D chart library for the Java(tm) platform * =========================================================== * * (C)opyright 2013-2022, by David Gilbert. All rights reserved. * * https://github.com/jfree/orson-charts * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . * * [Oracle and Java are registered trademarks of Oracle and/or its affiliates. * Other names may be trademarks of their respective owners.] * * If you do not wish to be bound by the terms of the GPL, an alternative * commercial license can be purchased. For details, please see visit the * Orson Charts home page: * * http://www.object-refinery.com/orsoncharts/index.html * */ package org.jfree.chart3d.graphics3d.internal; import java.util.List; import org.jfree.chart3d.graphics3d.Face; import org.jfree.chart3d.graphics3d.Point3D; /** * An interface that must be implemented by objects that can sort faces prior * to rendering (the Painter's algorithm). * * @since 1.3 */ public interface FaceSorter { /** * Returns a list of faces in the order that they should be painted. * * @param faces the faces before sorting ({@code null} not permitted). * @param eyePts the points in 3D space relative to the viewing position. * * @return An ordered list (note that the result may be the same list * passed in via the {@code faces} argument). */ List sort(List faces, Point3D[] eyePts); } orson-charts-2.1.0/src/main/java/org/jfree/chart3d/graphics3d/internal/StandardFaceSorter.java000066400000000000000000000036631417331271500322420ustar00rootroot00000000000000/* =========================================================== * Orson Charts : a 3D chart library for the Java(tm) platform * =========================================================== * * (C)opyright 2013-2022, by David Gilbert. All rights reserved. * * https://github.com/jfree/orson-charts * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . * * [Oracle and Java are registered trademarks of Oracle and/or its affiliates. * Other names may be trademarks of their respective owners.] * * If you do not wish to be bound by the terms of the GPL, an alternative * commercial license can be purchased. For details, please see visit the * Orson Charts home page: * * http://www.object-refinery.com/orsoncharts/index.html * */ package org.jfree.chart3d.graphics3d.internal; import java.io.Serializable; import java.util.List; import org.jfree.chart3d.graphics3d.Face; import org.jfree.chart3d.graphics3d.Point3D; /** * A face sorter that orders the faces by z-value. * * @since 1.3 */ public class StandardFaceSorter implements FaceSorter, Serializable { /** * Creates a new instance. */ public StandardFaceSorter() { // nothing to do } @Override public List sort(List faces, Point3D[] eyePts) { faces.sort(new ZOrderComparator(eyePts)); return faces; } } orson-charts-2.1.0/src/main/java/org/jfree/chart3d/graphics3d/internal/TaggedFace.java000066400000000000000000000044411417331271500304710ustar00rootroot00000000000000/* =========================================================== * Orson Charts : a 3D chart library for the Java(tm) platform * =========================================================== * * (C)opyright 2013-2022, by David Gilbert. All rights reserved. * * https://github.com/jfree/orson-charts * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . * * [Oracle and Java are registered trademarks of Oracle and/or its affiliates. * Other names may be trademarks of their respective owners.] * * If you do not wish to be bound by the terms of the GPL, an alternative * commercial license can be purchased. For details, please see visit the * Orson Charts home page: * * http://www.object-refinery.com/orsoncharts/index.html * */ package org.jfree.chart3d.graphics3d.internal; import org.jfree.chart3d.graphics3d.Face; import org.jfree.chart3d.graphics3d.Object3D; import org.jfree.chart3d.internal.Args; /** * A face belonging to an {@link Object3D} that has a tag. * * @since 1.3 */ public class TaggedFace extends Face { /** The tag. */ private String tag; /** * Creates a new instance. * * @param owner the owner ({@code null} not permitted). * @param vertices the vertices (must contain at least 3 vertices). * @param tag the tag ({@code null} not permitted). */ public TaggedFace(Object3D owner, int[] vertices, String tag) { super(owner, vertices); Args.nullNotPermitted(tag, "tag"); this.tag = tag; } /** * Returns the tag that was specified in the constructor. * * @return The tag (never {@code null}). */ @Override public String getTag() { return this.tag; } } orson-charts-2.1.0/src/main/java/org/jfree/chart3d/graphics3d/internal/Utils2D.java000066400000000000000000000166241417331271500300130ustar00rootroot00000000000000/* =========================================================== * Orson Charts : a 3D chart library for the Java(tm) platform * =========================================================== * * (C)opyright 2013-2022, by David Gilbert. All rights reserved. * * https://github.com/jfree/orson-charts * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . * * [Oracle and Java are registered trademarks of Oracle and/or its affiliates. * Other names may be trademarks of their respective owners.] * * If you do not wish to be bound by the terms of the GPL, an alternative * commercial license can be purchased. For details, please see visit the * Orson Charts home page: * * http://www.object-refinery.com/orsoncharts/index.html * */ package org.jfree.chart3d.graphics3d.internal; import java.awt.Dimension; import java.awt.geom.Line2D; import java.awt.geom.Point2D; /** * A collection of utility methods for 2D geometry. */ public class Utils2D { private Utils2D() { // no need to instantiate } /** * Returns {@code true} if the specified value is spanned by the * two bounds, and {@code false} otherwise. * * @param value the value. * @param bound1 the first boundary. * @param bound2 the second boundary. * * @return A boolean. */ public static boolean spans(double value, double bound1, double bound2) { return (bound1 < value && bound2 > value) || (bound1 > value && bound2 < value); } /** * Calculates twice the area of a triangle for points specified in * counter-clockwise order (if the points are specified in clockwise order * the result will be negative). * * @param a the first point ({@code null} not permitted). * @param b the second point ({@code null} not permitted). * @param c the third point ({@code null} not permitted). * * @return The area x 2. */ public static double area2(Point2D a, Point2D b, Point2D c) { double ax = a.getX(); double ay = a.getY(); double bx = b.getX(); double by = b.getY(); double cx = c.getX(); double cy = c.getY(); return (ax - cx) * (by - cy) - (ay - cy) * (bx - cx); } /** * Returns the point in the center of the four supplied points. * * @param pt0 point 0 ({@code null} not permitted). * @param pt1 point 1 ({@code null} not permitted). * @param pt2 point 2 ({@code null} not permitted). * @param pt3 point 3 ({@code null} not permitted). * * @return The center point (never {@code null}). */ public static Point2D centerPoint(Point2D pt0, Point2D pt1, Point2D pt2, Point2D pt3) { float x = (float) ((pt0.getX() + pt1.getX() + pt2.getX() + pt3.getX()) / 4.0); float y = (float) ((pt0.getY() + pt1.getY() + pt2.getY() + pt3.getY()) / 4.0); return new Point2D.Float(x, y); } /** * Returns the dimensions of the smallest rectangle that could contain * the supplied points. * * @param pts an array of points ({@code null} not permitted). * * @return The dimensions. */ public static Dimension findDimension(Point2D[] pts) { double minx = Double.POSITIVE_INFINITY; double maxx = Double.NEGATIVE_INFINITY; double miny = Double.POSITIVE_INFINITY; double maxy = Double.NEGATIVE_INFINITY; for (Point2D pt : pts) { minx = Math.min(minx, pt.getX()); maxx = Math.max(maxx, pt.getX()); miny = Math.min(miny, pt.getY()); maxy = Math.max(maxy, pt.getY()); } return new Dimension((int) (maxx - minx), (int) (maxy - miny)); } /** * Creates and returns a line that is perpendicular to the specified line. * * @param line the reference line ({@code null} not permitted). * @param b the base point, expressed as a percentage along the length of * the reference line. * @param size the size or length of the perpendicular line. * @param opposingPoint an opposing point, to define which side of the * reference line the perpendicular line will extend ({@code null} * not permitted). * * @return The perpendicular line. */ public static Line2D createPerpendicularLine(Line2D line, double b, double size, Point2D opposingPoint) { double dx = line.getX2() - line.getX1(); double dy = line.getY2() - line.getY1(); double length = Math.sqrt(dx * dx + dy * dy); double pdx = dy / length; double pdy = -dx / length; int ccw = line.relativeCCW(opposingPoint); Point2D pt1 = new Point2D.Double(line.getX1() + b * dx, line.getY1() + b * dy); Point2D pt2 = new Point2D.Double(pt1.getX() - ccw * size * pdx, pt1.getY() - ccw * size * pdy); return new Line2D.Double(pt1, pt2); } /** * Creates and returns a line that is perpendicular to the specified * line. * * @param line the reference line ({@code null} not permitted). * @param pt1 a point on the reference line ({@code null} not * permitted). * @param size the length of the new line. * @param opposingPoint an opposing point, to define which side of the * reference line the perpendicular line will extend ({@code null} * not permitted). * * @return The perpendicular line. */ public static Line2D createPerpendicularLine(Line2D line, Point2D pt1, double size, Point2D opposingPoint) { double dx = line.getX2() - line.getX1(); double dy = line.getY2() - line.getY1(); double length = Math.sqrt(dx * dx + dy * dy); double pdx = dy / length; double pdy = -dx / length; int ccw = line.relativeCCW(opposingPoint); Point2D pt2 = new Point2D.Double(pt1.getX() - ccw * size * pdx, pt1.getY() - ccw * size * pdy); return new Line2D.Double(pt1, pt2); } /** * Returns the angle of rotation (in radians) for the specified line. * * @param line the line ({@code null} not permitted). * * @return The angle of rotation (in radians). */ public static double calculateTheta(Line2D line) { double dx = line.getX2() - line.getX1(); double dy = line.getY2() - line.getY1(); return Math.atan2(dy, dx); } /** * Returns the length of the line. * * @param line the line ({@code null} not permitted). * * @return The length of the line. */ public static double length(Line2D line) { double dx = line.getX2() - line.getX1(); double dy = line.getY2() - line.getY1(); return Math.sqrt(dx * dx + dy * dy); } } orson-charts-2.1.0/src/main/java/org/jfree/chart3d/graphics3d/internal/Utils3D.java000066400000000000000000000076351417331271500300160ustar00rootroot00000000000000/* =========================================================== * Orson Charts : a 3D chart library for the Java(tm) platform * =========================================================== * * (C)opyright 2013-2022, by David Gilbert. All rights reserved. * * https://github.com/jfree/orson-charts * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . * * [Oracle and Java are registered trademarks of Oracle and/or its affiliates. * Other names may be trademarks of their respective owners.] * * If you do not wish to be bound by the terms of the GPL, an alternative * commercial license can be purchased. For details, please see visit the * Orson Charts home page: * * http://www.object-refinery.com/orsoncharts/index.html * */ package org.jfree.chart3d.graphics3d.internal; import org.jfree.chart3d.graphics3d.Point3D; /** * A collection of utility methods for 3D geometry. */ public class Utils3D { private Utils3D() { // no need to instantiate this class } /** * Returns the length of the vector v. * * @param v the vector ({@code null} not permitted). * * @return The length. */ public static double length(Point3D v) { return Math.sqrt(v.x * v.x + v.y * v.y + v.z * v.z); } /** * Returns a new vector that is the normalised form of the specified * vector. * * @param v the vector ({@code null} not permitted). * * @return The normalised form of the specified vector. * * @since 1.2 */ public static Point3D normalise(Point3D v) { double length = length(v); return new Point3D(v.x / length, v.y / length, v.z / length); } /** * Returns the scalar product of two vectors. * * @param a vector A ({@code null} not permitted). * @param b vector B ({@code null} not permitted). * * @return The scalar product. */ public static double scalarprod(Point3D a, Point3D b) { return a.x * b.x + a.y * b.y + a.z * b.z; } /** * Returns the normal vector for the plane defined by three points. * * @param a point A ({@code null} not permitted). * @param b point B ({@code null} not permitted). * @param c point C ({@code null} not permitted). * * @return The normal vector. */ public static Point3D normal(Point3D a, Point3D b, Point3D c) { double ax = a.x - c.x; double ay = a.y - c.y; double az = a.z - c.z; double bx = b.x - c.x; double by = b.y - c.y; double bz = b.z - c.z; return new Point3D(ay * bz - az * by, az * bx - ax * bz, ax * by - ay * bx); } /** * Returns the angle between the two vectors. * * @param a vector A ({@code null} not permitted). * @param b vector B ({@code null} not permitted). * * @return The (positive) angle in radians. */ public static double angle(Point3D a, Point3D b) { double dp = a.x * b.x + a.y * b.y + a.z * b.z; double alen = length(a); double blen = length(b); double c = dp / (alen * blen); // rounding can cause abs(c) to be greater than one, let's sweep that // under the carpet... c = Math.max(-1.0, Math.min(1.0, c)); return Math.acos(c); } } orson-charts-2.1.0/src/main/java/org/jfree/chart3d/graphics3d/internal/ZOrderComparator.java000066400000000000000000000041701417331271500317530ustar00rootroot00000000000000/* =========================================================== * Orson Charts : a 3D chart library for the Java(tm) platform * =========================================================== * * (C)opyright 2013-2022, by David Gilbert. All rights reserved. * * https://github.com/jfree/orson-charts * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . * * [Oracle and Java are registered trademarks of Oracle and/or its affiliates. * Other names may be trademarks of their respective owners.] * * If you do not wish to be bound by the terms of the GPL, an alternative * commercial license can be purchased. For details, please see visit the * Orson Charts home page: * * http://www.object-refinery.com/orsoncharts/index.html * */ package org.jfree.chart3d.graphics3d.internal; import java.util.Comparator; import org.jfree.chart3d.graphics3d.Face; import org.jfree.chart3d.graphics3d.Point3D; /** * A comparator that orders {@link Face} instances by Z-order. */ public class ZOrderComparator implements Comparator { Point3D[] pts; /** * Creates a new comparator. * * @param pts the points. */ public ZOrderComparator(Point3D[] pts) { this.pts = pts; } /* (non-Javadoc) * @see java.util.Comparator#compare(java.lang.Object, java.lang.Object) */ @Override public int compare(Face f1, Face f2) { double z1 = f1.calculateAverageZValue(this.pts); double z2 = f2.calculateAverageZValue(this.pts); return Double.compare(z1, z2); } } orson-charts-2.1.0/src/main/java/org/jfree/chart3d/graphics3d/package-info.java000066400000000000000000000004201417331271500272200ustar00rootroot00000000000000/** * The core 3D graphics rendering engine which is fully implemented using * the Java2D (Graphics2D) API. This engine is intended to have a general * purpose function, you should find no chart-specific code in this package. */ package org.jfree.chart3d.graphics3d; orson-charts-2.1.0/src/main/java/org/jfree/chart3d/graphics3d/swing/000077500000000000000000000000001417331271500251645ustar00rootroot00000000000000orson-charts-2.1.0/src/main/java/org/jfree/chart3d/graphics3d/swing/DisplayPanel3D.java000066400000000000000000000244601417331271500306110ustar00rootroot00000000000000/* =========================================================== * Orson Charts : a 3D chart library for the Java(tm) platform * =========================================================== * * (C)opyright 2013-2022, by David Gilbert. All rights reserved. * * https://github.com/jfree/orson-charts * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . * * [Oracle and Java are registered trademarks of Oracle and/or its affiliates. * Other names may be trademarks of their respective owners.] * * If you do not wish to be bound by the terms of the GPL, an alternative * commercial license can be purchased. For details, please see visit the * Orson Charts home page: * * http://www.object-refinery.com/orsoncharts/index.html * */ package org.jfree.chart3d.graphics3d.swing; import java.awt.BorderLayout; import java.awt.Font; import java.awt.FontFormatException; import java.awt.event.MouseEvent; import java.awt.event.MouseListener; import java.io.IOException; import java.io.InputStream; import java.util.logging.Level; import java.util.logging.Logger; import javax.swing.JButton; import javax.swing.JMenuItem; import javax.swing.JPanel; import javax.swing.JPopupMenu; import javax.swing.JToolBar; import javax.swing.JMenu; import org.jfree.chart3d.Resources; import org.jfree.chart3d.export.ExportFormat; import org.jfree.chart3d.export.ExportFormats; import org.jfree.chart3d.internal.Args; /** * A panel for displaying 3D content, with a toolbar and popup menu to control * the view. *

* NOTE: This class is serializable, but the serialization format is subject * to change in future releases and should not be relied upon for persisting * instances of this class. */ @SuppressWarnings("serial") public class DisplayPanel3D extends JPanel implements MouseListener { private static final int FONT_SIZE = 22; private static Font FONT_AWESOME; /** * Returns a font for "Font Awesome" (http://fontawesome.io) at the * specified size. * * @param size the point size. * * @return A font. */ public static Font getFontAwesomeFont(int size) { if (FONT_AWESOME == null) { try { InputStream in = DisplayPanel3D.class.getResourceAsStream( "fontawesome-webfont.ttf"); FONT_AWESOME = Font.createFont(Font.TRUETYPE_FONT, in); } catch (FontFormatException | IOException ex) { Logger.getLogger(Panel3D.class.getName()).log(Level.SEVERE, null, ex); } } return FONT_AWESOME.deriveFont(Font.PLAIN, size); } /** The 3D content. */ Panel3D content; /** The popup menu. */ private JPopupMenu popup; /** * Creates a new display panel for the given content, with a toolbar * and popup menu configured. * * @param content the content ({@code null} not permitted). */ public DisplayPanel3D(Panel3D content) { this(content, true, true); } /** * Creates a new display panel. * * @param content the content ({@code null} not permitted). * @param toolbar toolbar? * @param popupMenu popup menu? */ public DisplayPanel3D(Panel3D content, boolean toolbar, boolean popupMenu) { super(new BorderLayout()); this.content = content; add(this.content); if (toolbar) { JToolBar tb = createToolBar(content); add(tb, BorderLayout.EAST); } if (popupMenu) { this.popup = createPopupMenu(ExportFormat.values()); } this.content.addMouseListener(this); } /** * Returns a reference to the content panel. * * @return A reference to the content panel. */ public Panel3D getContent() { return this.content; } /** * Sets the list of export formats that will be shown in the popup menu. * If you provide an empty list, there will be no export submenu in the * popup menu. * * @param formats the list of formats ({@code null} not permitted). * * @since 1.2 */ public void setExportFormats(ExportFormat... formats) { // defer argument checking this.popup = createPopupMenu(formats); } /** * Creates the toolbar used to control zooming etc. * * @param content the 3D content that will be updated by toolbar actions. * * @return The toolbar. */ private JToolBar createToolBar(Panel3D content) { JToolBar tb = new JToolBar(JToolBar.VERTICAL); Font font = getFontAwesomeFont(FONT_SIZE); JButton zoomInButton = new JButton(new ZoomInAction(this.content, true)); zoomInButton.setFont(font); JButton zoomOutButton = new JButton(new ZoomOutAction(this.content, true)); zoomOutButton.setFont(font); JButton zoomToFitButton = new JButton(new ZoomToFitAction(this.content, true)); zoomToFitButton.setFont(font); JButton leftButton = new JButton(new LeftAction(content)); leftButton.setFont(font); JButton rightButton = new JButton(new RightAction(content)); rightButton.setFont(font); JButton upButton = new JButton(new UpAction(content)); upButton.setFont(font); JButton downButton = new JButton(new DownAction(content)); downButton.setFont(font); JButton rotateLeftButton = new JButton(new RollLeftAction(content)); rotateLeftButton.setFont(font); JButton rotateRightButton = new JButton(new RollRightAction(content)); rotateRightButton.setFont(font); tb.add(zoomInButton); tb.add(zoomOutButton); tb.add(zoomToFitButton); tb.add(new JToolBar.Separator()); tb.add(leftButton); tb.add(rightButton); tb.add(upButton); tb.add(downButton); tb.add(rotateLeftButton); tb.add(rotateRightButton); return tb; } /** * Creates a popup menu containing zooming items plus, if exportFormats * is not empty, a submenu of export items. * * @param exportFormats an ordered list of export formats to add to the * submenu ({@code null} not permitted). * * @return A popup menu. */ private JPopupMenu createPopupMenu(ExportFormat... exportFormats) { Args.nullNotPermitted(exportFormats, "exportFormats"); JPopupMenu popupMenu = new JPopupMenu(); popupMenu.add(new JMenuItem(new ZoomInAction(this.content, false))); popupMenu.add(new JMenuItem(new ZoomOutAction(this.content, false))); popupMenu.add(new JMenuItem(new ZoomToFitAction(this.content, false))); if (exportFormats.length > 0) { JMenu exportSubMenu = new JMenu(Resources.localString("EXPORT_AS")); for (ExportFormat f : exportFormats) { if (f.equals(ExportFormat.PNG)) { JMenuItem pngItem = new JMenuItem(new ExportToPNGAction( this.content)); exportSubMenu.add(pngItem); } else if (f.equals(ExportFormat.JPEG)) { JMenuItem jpgItem = new JMenuItem(new ExportToJPEGAction( this.content)); exportSubMenu.add(jpgItem); } else if (f.equals(ExportFormat.PDF)) { if (ExportFormats.isJFreePDFAvailable()) { JMenuItem pdfItem = new JMenuItem(new ExportToPDFAction( this.content)); exportSubMenu.add(pdfItem); } } else if (f.equals(ExportFormat.SVG)) { if (ExportFormats.isJFreeSVGAvailable()) { JMenuItem svgItem = new JMenuItem(new ExportToSVGAction( this.content)); exportSubMenu.add(svgItem); } } } if (exportSubMenu.getItemCount() > 0) { popupMenu.addSeparator(); popupMenu.add(exportSubMenu); } } return popupMenu; } /** * This method does nothing. * * @param e the mouse event. */ @Override public void mouseClicked(MouseEvent e) { // nothing to do } /** * Checks if the popup is triggered in which case it is displayed. * * @param e the mouse event. */ @Override public void mousePressed(MouseEvent e) { // popup is triggered on mousePressed for Linux and Mac, but Windows // is mouseReleased if (e.isPopupTrigger()) { if (this.popup != null) { this.popup.show(this, e.getX(), e.getY()); e.consume(); } } } /** * Checks if the popup is triggered in which case it is displayed. * * @param e the mouse event. */ @Override public void mouseReleased(MouseEvent e) { // popup is triggered on mouseReleased for Windows, but Linux and Mac // is mousePressed if (e.isPopupTrigger()) { if (this.popup != null) { this.popup.show(this, e.getX(), e.getY()); e.consume(); } } } /** * This method does nothing. * * @param e the mouse event. */ @Override public void mouseEntered(MouseEvent e) { // nothing to do } /** * This method does nothing. * * @param e the mouse event. */ @Override public void mouseExited(MouseEvent e) { // nothing to do } } orson-charts-2.1.0/src/main/java/org/jfree/chart3d/graphics3d/swing/DownAction.java000066400000000000000000000050471417331271500301020ustar00rootroot00000000000000/* =========================================================== * Orson Charts : a 3D chart library for the Java(tm) platform * =========================================================== * * (C)opyright 2013-2022, by David Gilbert. All rights reserved. * * https://github.com/jfree/orson-charts * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . * * [Oracle and Java are registered trademarks of Oracle and/or its affiliates. * Other names may be trademarks of their respective owners.] * * If you do not wish to be bound by the terms of the GPL, an alternative * commercial license can be purchased. For details, please see visit the * Orson Charts home page: * * http://www.object-refinery.com/orsoncharts/index.html * */ package org.jfree.chart3d.graphics3d.swing; import java.awt.event.ActionEvent; import javax.swing.AbstractAction; import javax.swing.Action; import org.jfree.chart3d.Resources; import org.jfree.chart3d.internal.Args; /** * An action that handles rotating the 3D view towards the bottom of the screen. *

* NOTE: This class is serializable, but the serialization format is subject * to change in future releases and should not be relied upon for persisting * instances of this class. */ @SuppressWarnings("serial") public class DownAction extends AbstractAction { private final Panel3D panel; /** * Creates a new action associated with the specified panel. * * @param panel the panel ({@code null} not permitted). */ public DownAction(Panel3D panel) { super("\uF063"); Args.nullNotPermitted(panel, "panel"); this.panel = panel; putValue(Action.SHORT_DESCRIPTION, Resources.localString("DOWN_ACTION_SHORT_DESCRIPTION")); } @Override public void actionPerformed(ActionEvent e) { double delta = this.panel.getRotateIncrement(); this.panel.getViewPoint().moveUpDown(-delta); this.panel.repaint(); } } orson-charts-2.1.0/src/main/java/org/jfree/chart3d/graphics3d/swing/ExportToJPEGAction.java000066400000000000000000000076051417331271500314270ustar00rootroot00000000000000/* =========================================================== * Orson Charts : a 3D chart library for the Java(tm) platform * =========================================================== * * (C)opyright 2013-2022, by David Gilbert. All rights reserved. * * https://github.com/jfree/orson-charts * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . * * [Oracle and Java are registered trademarks of Oracle and/or its affiliates. * Other names may be trademarks of their respective owners.] * * If you do not wish to be bound by the terms of the GPL, an alternative * commercial license can be purchased. For details, please see visit the * Orson Charts home page: * * http://www.object-refinery.com/orsoncharts/index.html * */ package org.jfree.chart3d.graphics3d.swing; import java.awt.Graphics2D; import java.awt.Rectangle; import java.awt.event.ActionEvent; import java.awt.geom.Dimension2D; import java.awt.image.BufferedImage; import java.io.File; import java.io.IOException; import javax.imageio.ImageIO; import javax.swing.AbstractAction; import javax.swing.JFileChooser; import javax.swing.filechooser.FileNameExtensionFilter; import org.jfree.chart3d.Resources; import org.jfree.chart3d.internal.Args; /** * An action that handles saving the content of a panel to a JPEG image. *

* NOTE: This class is serializable, but the serialization format is subject * to change in future releases and should not be relied upon for persisting * instances of this class. * * @since 1.2 */ @SuppressWarnings("serial") public class ExportToJPEGAction extends AbstractAction { /** The panel to which this action applies. */ private final Panel3D panel; /** * Creates a new action instance. * * @param panel the panel ({@code null} not permitted). */ public ExportToJPEGAction(Panel3D panel) { super(Resources.localString("JPG_MENU_LABEL")); Args.nullNotPermitted(panel, "panel"); this.panel = panel; } /** * Writes the content of the panel to a PNG image, using Java's ImageIO. * * @param e the event. */ @Override public void actionPerformed(ActionEvent e) { JFileChooser fileChooser = new JFileChooser(); FileNameExtensionFilter filter = new FileNameExtensionFilter( Resources.localString("JPG_FILE_FILTER_DESCRIPTION"), "jpg"); fileChooser.addChoosableFileFilter(filter); fileChooser.setFileFilter(filter); int option = fileChooser.showSaveDialog(this.panel); if (option == JFileChooser.APPROVE_OPTION) { String filename = fileChooser.getSelectedFile().getPath(); if (!filename.endsWith(".jpg")) { filename = filename + ".jpg"; } Dimension2D size = this.panel.getSize(); int w = (int) size.getWidth(); int h = (int) size.getHeight(); BufferedImage image = new BufferedImage(w, h, BufferedImage.TYPE_INT_RGB); Graphics2D g2 = image.createGraphics(); this.panel.getDrawable().draw(g2, new Rectangle(w, h)); try { ImageIO.write(image, "jpeg", new File(filename)); } catch (IOException ex) { throw new RuntimeException(ex); } } } } orson-charts-2.1.0/src/main/java/org/jfree/chart3d/graphics3d/swing/ExportToPDFAction.java000066400000000000000000000064641417331271500313150ustar00rootroot00000000000000/* =========================================================== * Orson Charts : a 3D chart library for the Java(tm) platform * =========================================================== * * (C)opyright 2013-2022, by David Gilbert. All rights reserved. * * https://github.com/jfree/orson-charts * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . * * [Oracle and Java are registered trademarks of Oracle and/or its affiliates. * Other names may be trademarks of their respective owners.] * * If you do not wish to be bound by the terms of the GPL, an alternative * commercial license can be purchased. For details, please see visit the * Orson Charts home page: * * http://www.object-refinery.com/orsoncharts/index.html * */ package org.jfree.chart3d.graphics3d.swing; import java.awt.event.ActionEvent; import java.io.File; import javax.swing.AbstractAction; import javax.swing.JFileChooser; import javax.swing.filechooser.FileNameExtensionFilter; import org.jfree.chart3d.Resources; import org.jfree.chart3d.internal.Args; /** * An action that handles saving the content of a panel to a PDF file using * Orson PDF. *

* NOTE: This class is serializable, but the serialization format is subject * to change in future releases and should not be relied upon for persisting * instances of this class. */ @SuppressWarnings("serial") public class ExportToPDFAction extends AbstractAction { /** The panel to which this action applies. */ private final Panel3D panel; /** * Creates a new action. * * @param panel the panel that the action applies to ({@code null} * not permitted). */ public ExportToPDFAction(Panel3D panel) { super(Resources.localString("PDF_MENU_LABEL")); Args.nullNotPermitted(panel, NAME); this.panel = panel; } /** * Writes the content of the panel to a PDF file, using Orson PDF. * * @param e the event. */ @Override public void actionPerformed(ActionEvent e) { JFileChooser fileChooser = new JFileChooser(); FileNameExtensionFilter filter = new FileNameExtensionFilter( Resources.localString("PDF_FILE_FILTER_DESCRIPTION"), "pdf"); fileChooser.addChoosableFileFilter(filter); fileChooser.setFileFilter(filter); int option = fileChooser.showSaveDialog(this.panel); if (option == JFileChooser.APPROVE_OPTION) { String filename = fileChooser.getSelectedFile().getPath(); if (!filename.endsWith(".pdf")) { filename = filename + ".pdf"; } this.panel.writeAsPDF(new File(filename), this.panel.getWidth(), this.panel.getHeight()); } } } orson-charts-2.1.0/src/main/java/org/jfree/chart3d/graphics3d/swing/ExportToPNGAction.java000066400000000000000000000075531417331271500313300ustar00rootroot00000000000000/* =========================================================== * Orson Charts : a 3D chart library for the Java(tm) platform * =========================================================== * * (C)opyright 2013-2022, by David Gilbert. All rights reserved. * * https://github.com/jfree/orson-charts * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . * * [Oracle and Java are registered trademarks of Oracle and/or its affiliates. * Other names may be trademarks of their respective owners.] * * If you do not wish to be bound by the terms of the GPL, an alternative * commercial license can be purchased. For details, please see visit the * Orson Charts home page: * * http://www.object-refinery.com/orsoncharts/index.html * */ package org.jfree.chart3d.graphics3d.swing; import java.awt.Graphics2D; import java.awt.Rectangle; import java.awt.event.ActionEvent; import java.awt.geom.Dimension2D; import java.awt.image.BufferedImage; import java.io.File; import java.io.IOException; import javax.imageio.ImageIO; import javax.swing.AbstractAction; import javax.swing.JFileChooser; import javax.swing.filechooser.FileNameExtensionFilter; import org.jfree.chart3d.Resources; import org.jfree.chart3d.internal.Args; /** * An action that handles saving the content of a panel to a PNG image. *

* NOTE: This class is serializable, but the serialization format is subject * to change in future releases and should not be relied upon for persisting * instances of this class. */ @SuppressWarnings("serial") public class ExportToPNGAction extends AbstractAction { /** The panel to which this action applies. */ private final Panel3D panel; /** * Creates a new action instance. * * @param panel the panel ({@code null} not permitted). */ public ExportToPNGAction(Panel3D panel) { super(Resources.localString("PNG_MENU_LABEL")); Args.nullNotPermitted(panel, "panel"); this.panel = panel; } /** * Writes the content of the panel to a PNG image, using Java's ImageIO. * * @param e the event. */ @Override public void actionPerformed(ActionEvent e) { JFileChooser fileChooser = new JFileChooser(); FileNameExtensionFilter filter = new FileNameExtensionFilter( Resources.localString("PNG_FILE_FILTER_DESCRIPTION"), "png"); fileChooser.addChoosableFileFilter(filter); fileChooser.setFileFilter(filter); int option = fileChooser.showSaveDialog(this.panel); if (option == JFileChooser.APPROVE_OPTION) { String filename = fileChooser.getSelectedFile().getPath(); if (!filename.endsWith(".png")) { filename = filename + ".png"; } Dimension2D size = this.panel.getSize(); int w = (int) size.getWidth(); int h = (int) size.getHeight(); BufferedImage image = new BufferedImage(w, h, BufferedImage.TYPE_INT_ARGB); Graphics2D g2 = image.createGraphics(); this.panel.getDrawable().draw(g2, new Rectangle(w, h)); try { ImageIO.write(image, "png", new File(filename)); } catch (IOException ex) { throw new RuntimeException(ex); } } } } orson-charts-2.1.0/src/main/java/org/jfree/chart3d/graphics3d/swing/ExportToSVGAction.java000066400000000000000000000065161417331271500313410ustar00rootroot00000000000000/* =========================================================== * Orson Charts : a 3D chart library for the Java(tm) platform * =========================================================== * * (C)opyright 2013-2022, by David Gilbert. All rights reserved. * * https://github.com/jfree/orson-charts * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . * * [Oracle and Java are registered trademarks of Oracle and/or its affiliates. * Other names may be trademarks of their respective owners.] * * If you do not wish to be bound by the terms of the GPL, an alternative * commercial license can be purchased. For details, please see visit the * Orson Charts home page: * * http://www.object-refinery.com/orsoncharts/index.html * */ package org.jfree.chart3d.graphics3d.swing; import java.awt.event.ActionEvent; import java.io.File; import javax.swing.AbstractAction; import javax.swing.JFileChooser; import javax.swing.filechooser.FileNameExtensionFilter; import org.jfree.chart3d.Resources; import org.jfree.chart3d.internal.Args; /** * An action that handles saving the content of a panel to a Scalable Vector * Graphics (SVG) file using JFreeSVG. *

* NOTE: This class is serializable, but the serialization format is subject * to change in future releases and should not be relied upon for persisting * instances of this class. */ @SuppressWarnings("serial") public class ExportToSVGAction extends AbstractAction { /** The panel to which this action applies. */ private final Panel3D panel; /** * Creates a new action. * * @param panel the panel that the action applies to ({@code null} * not permitted). */ public ExportToSVGAction(Panel3D panel) { super(Resources.localString("SVG_MENU_LABEL")); Args.nullNotPermitted(panel, NAME); this.panel = panel; } /** * Writes the content of the panel to an SVG file, using JFreeSVG. * * @param e the event. */ @Override public void actionPerformed(ActionEvent e) { JFileChooser fileChooser = new JFileChooser(); FileNameExtensionFilter filter = new FileNameExtensionFilter( Resources.localString("SVG_FILE_FILTER_DESCRIPTION"), "svg"); fileChooser.addChoosableFileFilter(filter); fileChooser.setFileFilter(filter); int option = fileChooser.showSaveDialog(this.panel); if (option == JFileChooser.APPROVE_OPTION) { String filename = fileChooser.getSelectedFile().getPath(); if (!filename.endsWith(".svg")) { filename = filename + ".svg"; } this.panel.writeAsSVG(new File(filename), this.panel.getWidth(), this.panel.getHeight()); } } } orson-charts-2.1.0/src/main/java/org/jfree/chart3d/graphics3d/swing/LeftAction.java000066400000000000000000000047261417331271500300700ustar00rootroot00000000000000/* =========================================================== * Orson Charts : a 3D chart library for the Java(tm) platform * =========================================================== * * (C)opyright 2013-2022, by David Gilbert. All rights reserved. * * https://github.com/jfree/orson-charts * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . * * [Oracle and Java are registered trademarks of Oracle and/or its affiliates. * Other names may be trademarks of their respective owners.] * * If you do not wish to be bound by the terms of the GPL, an alternative * commercial license can be purchased. For details, please see visit the * Orson Charts home page: * * http://www.object-refinery.com/orsoncharts/index.html * */ package org.jfree.chart3d.graphics3d.swing; import java.awt.event.ActionEvent; import javax.swing.AbstractAction; import javax.swing.Action; import org.jfree.chart3d.Resources; import org.jfree.chart3d.internal.Args; /** * An action that handles rotating the 3D view towards the left of the screen. *

* NOTE: This class is serializable, but the serialization format is subject * to change in future releases and should not be relied upon for persisting * instances of this class. * * @see RightAction */ @SuppressWarnings("serial") public class LeftAction extends AbstractAction { private final Panel3D panel; /** * Creates a new action instance. * * @param panel the panel ({@code null} not permitted). */ public LeftAction(Panel3D panel) { super("\uF060"); Args.nullNotPermitted(panel, "panel"); this.panel = panel; putValue(Action.SHORT_DESCRIPTION, Resources.localString("LEFT_ACTION_SHORT_DESCRIPTION")); } @Override public void actionPerformed(ActionEvent e) { this.panel.panLeftRight(this.panel.getPanIncrement()); } } orson-charts-2.1.0/src/main/java/org/jfree/chart3d/graphics3d/swing/Panel3D.java000066400000000000000000000402711417331271500272610ustar00rootroot00000000000000/* =========================================================== * Orson Charts : a 3D chart library for the Java(tm) platform * =========================================================== * * (C)opyright 2013-2022, by David Gilbert. All rights reserved. * * https://github.com/jfree/orson-charts * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . * * [Oracle and Java are registered trademarks of Oracle and/or its affiliates. * Other names may be trademarks of their respective owners.] * * If you do not wish to be bound by the terms of the GPL, an alternative * commercial license can be purchased. For details, please see visit the * Orson Charts home page: * * http://www.object-refinery.com/orsoncharts/index.html * */ package org.jfree.chart3d.graphics3d.swing; import java.awt.BorderLayout; import java.awt.Dimension; import java.awt.Graphics; import java.awt.Graphics2D; import java.awt.Insets; import java.awt.Point; import java.awt.Rectangle; import java.awt.geom.AffineTransform; import java.awt.event.MouseEvent; import java.awt.event.MouseListener; import java.awt.event.MouseMotionListener; import java.awt.event.MouseWheelEvent; import java.awt.event.MouseWheelListener; import java.awt.geom.Dimension2D; import java.io.File; import javax.swing.JPanel; import javax.swing.ToolTipManager; import org.jfree.chart3d.internal.Args; import org.jfree.chart3d.export.ExportUtils; import org.jfree.chart3d.graphics3d.Dimension3D; import org.jfree.chart3d.graphics3d.Drawable3D; import org.jfree.chart3d.graphics3d.Offset2D; import org.jfree.chart3d.graphics3d.RenderingInfo; import org.jfree.chart3d.graphics3d.ViewPoint3D; /** * A panel that displays a set of 3D objects from a particular viewing point. * The view point is maintained by the {@link Drawable3D} but the panel * provides convenience methods to get/set it. *

* NOTE: This class is serializable, but the serialization format is subject * to change in future releases and should not be relied upon for persisting * instances of this class. */ @SuppressWarnings("serial") public class Panel3D extends JPanel implements MouseListener, MouseMotionListener, MouseWheelListener { /** * The object that is displayed in the panel. */ private final Drawable3D drawable; /** * The minimum viewing distance (zooming in will not go closer than this). */ private final double minViewingDistance; private double maxViewingDistanceMultiplier; /** * The margin to leave around the edges of the chart when zooming to fit. * This is expressed as a percentage (0.25 = 25 percent) of the width * and height. */ private double margin; /** The angle increment for panning left and right (in radians). */ private double panIncrement; /** The angle increment for rotating up and down (in radians). */ private double rotateIncrement; /** The roll increment (in radians). */ private double rollIncrement; /** * The (screen) point of the last mouse click (will be {@code null} * initially). Used to calculate the mouse drag distance and direction. */ private Point lastClickPoint; /** * The (screen) point of the last mouse move point that was handled. */ private Point lastMovePoint; /** * Temporary state to track the 2D offset during an ALT-mouse-drag * operation. */ private Offset2D offsetAtMousePressed; private RenderingInfo renderingInfo; /** * Creates a new panel with the specified {@link Drawable3D} to * display. * * @param drawable the content to display ({@code null} not * permitted). */ public Panel3D(Drawable3D drawable) { super(new BorderLayout()); Args.nullNotPermitted(drawable, "drawable"); this.drawable = drawable; this.margin = 0.25; this.minViewingDistance = drawable.getDimensions().getDiagonalLength(); this.maxViewingDistanceMultiplier = 8.0; this.panIncrement = Math.PI / 60; this.rotateIncrement = Math.PI / 60; this.rollIncrement = Math.PI / 60; addMouseListener(this); addMouseMotionListener(this); addMouseWheelListener(this); } /** * Returns the {@code Drawable3D} object that is displayed in this * panel. This is specified via the panel constructor and there is no * setter method to change it. * * @return The {@code Drawable3D} object (never {@code null}). */ public Drawable3D getDrawable() { return this.drawable; } /** * Returns the margin, expressed as a percentage, that controls the amount * of space to leave around the edges of the 3D content when the * {@code zoomToFit()} method is called. The default value is * {@code 0.25} (25 percent). * * @return The margin. */ public double getMargin() { return this.margin; } /** * Sets the margin that controls the amount of space to leave around the * edges of the 3D content when the {@code zoomToFit()} method is * called. * * @param margin the margin (as a percentage, where 0.25 = 25 percent). */ public void setMargin(double margin) { this.margin = margin; } /** * Returns the minimum viewing distance. Zooming by mouse wheel or other * means will not move the viewing point closer than this. The value * is computed in the constructor from the dimensions of the drawable * object. * * @return The minimum viewing distance. */ public double getMinViewingDistance() { return this.minViewingDistance; } /** * Returns the multiplier for the maximum viewing distance (a multiple of * the minimum viewing distance). The default value is {@code 8.0}. * * @return The multiplier. * * @since 1.3 */ public double getMaxViewingDistanceMultiplier() { return this.maxViewingDistanceMultiplier; } /** * Sets the multiplier used to calculate the maximum viewing distance. * * @param multiplier the new multiplier. * * @since 1.3 */ public void setMaxViewingDistanceMultiplier(double multiplier) { this.maxViewingDistanceMultiplier = multiplier; } /** * Returns the angle delta for each pan left or right. The default * value is {@code Math.PI / 60}. * * @return The angle delta (in radians). */ public double getPanIncrement() { return panIncrement; } /** * Sets the standard increment for panning left and right (a rotation * specified in radians). * * @param panIncrement the increment (in radians). */ public void setPanIncrement(double panIncrement) { this.panIncrement = panIncrement; } /** * Returns the angle delta for each rotate up or down. The default * value is {@code Math.PI / 60}. * * @return The angle delta (in radians). */ public double getRotateIncrement() { return rotateIncrement; } /** * Sets the vertical (up and down) rotation increment (in radians). * * @param rotateIncrement the increment (in radians). */ public void setRotateIncrement(double rotateIncrement) { this.rotateIncrement = rotateIncrement; } /** * Returns the angle delta for each roll operation. The default * value is {@code Math.PI / 60}. * * @return The angle delta (in radians). */ public double getRollIncrement() { return rollIncrement; } /** * Sets the roll increment in radians. * * @param rollIncrement the increment (in radians). */ public void setRollIncrement(double rollIncrement) { this.rollIncrement = rollIncrement; } /** * Returns the view point that is maintained by the {@link Drawable3D} * instance on display. * * @return The view point (never {@code null}). */ public ViewPoint3D getViewPoint() { return this.drawable.getViewPoint(); } /** * Sets a new view point and repaints the panel. * * @param vp the view point ({@code null} not permitted). */ public void setViewPoint(ViewPoint3D vp) { Args.nullNotPermitted(vp, "vp"); this.drawable.setViewPoint(vp); // repaint(); } /** * Returns the last click point (possibly {@code null}). * * @return The last click point (possibly {@code null}). */ protected Point getLastClickPoint() { return this.lastClickPoint; } /** * Returns the rendering info from the previous call to * draw(). * * @return The rendering info (possibly {@code null}). */ protected RenderingInfo getRenderingInfo() { return this.renderingInfo; } /** * Rotates the view point around from left to right by the specified * angle and repaints the 3D scene. The direction relative to the * world coordinates depends on the orientation of the view point. * * @param angle the angle of rotation (in radians). */ public void panLeftRight(double angle) { this.drawable.getViewPoint().panLeftRight(angle); repaint(); } /** * Adjusts the viewing distance so that the chart fits the current panel * size. A margin is left (see {@link #getMargin()} around the edges to * leave room for labels etc. */ public void zoomToFit() { zoomToFit(getSize()); } /** * Adjusts the viewing distance so that the chart fits the specified * size. A margin is left (see {@link #getMargin()} around the edges to * leave room for labels etc. * * @param size the target size ({@code null} not permitted). */ public void zoomToFit(Dimension2D size) { int w = (int) (size.getWidth() * (1.0 - this.margin)); int h = (int) (size.getHeight() * (1.0 - this.margin)); Dimension2D target = new Dimension(w, h); Dimension3D d3d = this.drawable.getDimensions(); float distance = this.drawable.getViewPoint().optimalDistance(target, d3d, this.drawable.getProjDistance()); this.drawable.getViewPoint().setRho(distance); repaint(); } /** * Paints the panel by asking the drawable to render a 2D projection of the * objects it is managing. * * @param g the graphics target ({@code null} not permitted, assumed to be * an instance of {@code Graphics2D}). */ @Override public void paintComponent(Graphics g) { super.paintComponent(g); Graphics2D g2 = (Graphics2D) g; AffineTransform saved = g2.getTransform(); Dimension size = getSize(); Insets insets = getInsets(); Rectangle drawArea = new Rectangle(insets.left, insets.top, size.width - insets.left - insets.right, size.height - insets.top - insets.bottom); this.renderingInfo = this.drawable.draw(g2, drawArea); g2.setTransform(saved); } /** * Registers this component with the tool tip manager. * * @since 1.3 */ public void registerForTooltips() { ToolTipManager.sharedInstance().registerComponent(this); } /** * Unregisters this component with the tool tip manager. * * @since 1.3 */ public void unregisterForTooltips() { ToolTipManager.sharedInstance().unregisterComponent(this); } /* (non-Javadoc) * @see java.awt.event.MouseListener#mouseClicked(java.awt.event.MouseEvent) */ @Override public void mouseClicked(MouseEvent e) { // nothing to do } /* (non-Javadoc) * @see java.awt.event.MouseListener#mouseEntered(java.awt.event.MouseEvent) */ @Override public void mouseEntered(MouseEvent e) { // nothing to do } /* (non-Javadoc) * @see java.awt.event.MouseListener#mouseExited(java.awt.event.MouseEvent) */ @Override public void mouseExited(MouseEvent e) { // nothing to do } /* (non-Javadoc) * @see java.awt.event.MouseListener#mousePressed(java.awt.event.MouseEvent) */ @Override public void mousePressed(MouseEvent e) { this.lastClickPoint = e.getPoint(); this.lastMovePoint = this.lastClickPoint; this.offsetAtMousePressed = this.drawable.getTranslate2D(); } /* (non-Javadoc) * @see java.awt.event.MouseListener#mouseReleased(java.awt.event.MouseEvent) */ @Override public void mouseReleased(MouseEvent e) { // nothing to do } /* (non-Javadoc) * @see java.awt.event.MouseMotionListener#mouseDragged(java.awt.event.MouseEvent) */ @Override public void mouseDragged(MouseEvent e) { if (e.isAltDown()) { Point currPt = e.getPoint(); Offset2D offset = this.offsetAtMousePressed; Point lastPt = getLastClickPoint(); double dx = offset.getDX() + (currPt.x - lastPt.x); double dy = offset.getDY() + (currPt.y - lastPt.y); this.drawable.setTranslate2D(new Offset2D(dx, dy)); } else { Point currPt = e.getPoint(); int dx = currPt.x - this.lastMovePoint.x; int dy = currPt.y - this.lastMovePoint.y; this.lastMovePoint = currPt; this.drawable.getViewPoint().panLeftRight(-dx * Math.PI / 120); this.drawable.getViewPoint().moveUpDown(-dy * Math.PI / 120); repaint(); } } /* (non-Javadoc) * @see java.awt.event.MouseMotionListener#mouseMoved(java.awt.event.MouseEvent) */ @Override public void mouseMoved(MouseEvent e) { // nothing to do } /** * Receives notification of a mouse wheel movement and responds by moving * the viewpoint in or out (zooming). * * @param mwe the mouse wheel event. */ @Override public void mouseWheelMoved(MouseWheelEvent mwe) { float units = mwe.getUnitsToScroll(); double maxViewingDistance = this.maxViewingDistanceMultiplier * this.minViewingDistance; double valRho = Math.max(this.minViewingDistance, Math.min(maxViewingDistance, this.drawable.getViewPoint().getRho() + units)); this.drawable.getViewPoint().setRho(valRho); repaint(); } /** * Writes the current content to the specified file in PDF format. This * will only work when the OrsonPDF library is found on the classpath. * Reflection is used to ensure there is no compile-time dependency on * OrsonPDF (which is non-free software). * * @param file the output file ({@code null} not permitted). * @param w the chart width. * @param h the chart height. * * @deprecated Use ExportUtils.writeAsPDF() directly. */ void writeAsPDF(File file, int w, int h) { ExportUtils.writeAsPDF(drawable, w, h, file); } /** * Writes the current content to the specified file in SVG format. This * will only work when the JFreeSVG library is found on the classpath. * Reflection is used to ensure there is no compile-time dependency on * JFreeSVG. * * @param file the output file ({@code null} not permitted). * @param w the chart width. * @param h the chart height. * * @deprecated Use ExportUtils.writeAsPDF() directly. */ void writeAsSVG(File file, int w, int h) { ExportUtils.writeAsSVG(this.drawable, w, h, file); } } orson-charts-2.1.0/src/main/java/org/jfree/chart3d/graphics3d/swing/RightAction.java000066400000000000000000000047331417331271500302510ustar00rootroot00000000000000/* =========================================================== * Orson Charts : a 3D chart library for the Java(tm) platform * =========================================================== * * (C)opyright 2013-2022, by David Gilbert. All rights reserved. * * https://github.com/jfree/orson-charts * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . * * [Oracle and Java are registered trademarks of Oracle and/or its affiliates. * Other names may be trademarks of their respective owners.] * * If you do not wish to be bound by the terms of the GPL, an alternative * commercial license can be purchased. For details, please see visit the * Orson Charts home page: * * http://www.object-refinery.com/orsoncharts/index.html * */ package org.jfree.chart3d.graphics3d.swing; import java.awt.event.ActionEvent; import javax.swing.AbstractAction; import javax.swing.Action; import org.jfree.chart3d.Resources; import org.jfree.chart3d.internal.Args; /** * An action that handles rotating the 3D view towards the right of the screen. *

* NOTE: This class is serializable, but the serialization format is subject * to change in future releases and should not be relied upon for persisting * instances of this class. * * @see LeftAction */ @SuppressWarnings("serial") public class RightAction extends AbstractAction { private final Panel3D panel; /** * Creates a new action instance. * * @param panel the panel ({@code null} not permitted). */ public RightAction(Panel3D panel) { super("\uF061"); Args.nullNotPermitted(panel, "panel"); this.panel = panel; putValue(Action.SHORT_DESCRIPTION, Resources.localString("RIGHT_ACTION_SHORT_DESCRIPTION")); } @Override public void actionPerformed(ActionEvent e) { this.panel.panLeftRight(-this.panel.getPanIncrement()); } } orson-charts-2.1.0/src/main/java/org/jfree/chart3d/graphics3d/swing/RollLeftAction.java000066400000000000000000000052361417331271500307160ustar00rootroot00000000000000/* =========================================================== * Orson Charts : a 3D chart library for the Java(tm) platform * =========================================================== * * (C)opyright 2013-2022, by David Gilbert. All rights reserved. * * https://github.com/jfree/orson-charts * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . * * [Oracle and Java are registered trademarks of Oracle and/or its affiliates. * Other names may be trademarks of their respective owners.] * * If you do not wish to be bound by the terms of the GPL, an alternative * commercial license can be purchased. For details, please see visit the * Orson Charts home page: * * http://www.object-refinery.com/orsoncharts/index.html * */ package org.jfree.chart3d.graphics3d.swing; import java.awt.event.ActionEvent; import javax.swing.AbstractAction; import javax.swing.Action; import org.jfree.chart3d.Resources; import org.jfree.chart3d.internal.Args; /** * An action that handles rolling the 3D view counter-clockwise around an * axis from the viewing point to the origin. *

* NOTE: This class is serializable, but the serialization format is subject * to change in future releases and should not be relied upon for persisting * instances of this class. */ @SuppressWarnings("serial") public class RollLeftAction extends AbstractAction { private final Panel3D panel; /** * Creates a new action instance. * * @param panel the panel ({@code null} not permitted). */ public RollLeftAction(Panel3D panel) { super("\uF112"); Args.nullNotPermitted(panel, "panel"); this.panel = panel; putValue(Action.SHORT_DESCRIPTION, Resources.localString("ROLL_LEFT_ACTION_SHORT_DESCRIPTION")); } /** * Rotates the orientation of the view point and repaints the panel. * * @param e the action event. */ @Override public void actionPerformed(ActionEvent e) { this.panel.getViewPoint().roll(-this.panel.getRollIncrement()); this.panel.repaint(); } } orson-charts-2.1.0/src/main/java/org/jfree/chart3d/graphics3d/swing/RollRightAction.java000066400000000000000000000052321417331271500310750ustar00rootroot00000000000000/* =========================================================== * Orson Charts : a 3D chart library for the Java(tm) platform * =========================================================== * * (C)opyright 2013-2022, by David Gilbert. All rights reserved. * * https://github.com/jfree/orson-charts * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . * * [Oracle and Java are registered trademarks of Oracle and/or its affiliates. * Other names may be trademarks of their respective owners.] * * If you do not wish to be bound by the terms of the GPL, an alternative * commercial license can be purchased. For details, please see visit the * Orson Charts home page: * * http://www.object-refinery.com/orsoncharts/index.html * */ package org.jfree.chart3d.graphics3d.swing; import java.awt.event.ActionEvent; import javax.swing.AbstractAction; import javax.swing.Action; import org.jfree.chart3d.Resources; import org.jfree.chart3d.internal.Args; /** * An action that handles rolling the 3D view clockwise around an * axis from the viewing point to the origin. *

* NOTE: This class is serializable, but the serialization format is subject * to change in future releases and should not be relied upon for persisting * instances of this class. */ @SuppressWarnings("serial") public class RollRightAction extends AbstractAction { private final Panel3D panel; /** * Creates a new action instance. * * @param panel the panel ({@code null} not permitted). */ public RollRightAction(Panel3D panel) { super("\uF064"); Args.nullNotPermitted(panel, "panel"); this.panel = panel; putValue(Action.SHORT_DESCRIPTION, Resources.localString("ROLL_RIGHT_ACTION_SHORT_DESCRIPTION")); } /** * Rotates the orientation of the view point and repaints the panel. * * @param e the action event. */ @Override public void actionPerformed(ActionEvent e) { this.panel.getViewPoint().roll(this.panel.getRollIncrement()); this.panel.repaint(); } } orson-charts-2.1.0/src/main/java/org/jfree/chart3d/graphics3d/swing/UpAction.java000066400000000000000000000052611417331271500275550ustar00rootroot00000000000000/* =========================================================== * Orson Charts : a 3D chart library for the Java(tm) platform * =========================================================== * * (C)opyright 2013-2022, by David Gilbert. All rights reserved. * * https://github.com/jfree/orson-charts * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . * * [Oracle and Java are registered trademarks of Oracle and/or its affiliates. * Other names may be trademarks of their respective owners.] * * If you do not wish to be bound by the terms of the GPL, an alternative * commercial license can be purchased. For details, please see visit the * Orson Charts home page: * * http://www.object-refinery.com/orsoncharts/index.html * */ package org.jfree.chart3d.graphics3d.swing; import org.jfree.chart3d.internal.Args; import java.awt.event.ActionEvent; import javax.swing.AbstractAction; import javax.swing.Action; import org.jfree.chart3d.Resources; /** * An action that handles rotating the 3D view towards the top of the screen. *

* NOTE: This class is serializable, but the serialization format is subject * to change in future releases and should not be relied upon for persisting * instances of this class. */ @SuppressWarnings("serial") public class UpAction extends AbstractAction { /** The panel containing the 3D content. */ private final Panel3D panel; /** * Creates a new action associated with the specified panel. * * @param panel the panel ({@code null} not permitted). */ public UpAction(Panel3D panel) { super("\uF062"); Args.nullNotPermitted(panel, "panel"); this.panel = panel; putValue(Action.SHORT_DESCRIPTION, Resources.localString("UP_ACTION_SHORT_DESCRIPTION")); } /** * Performs the rotate up action. * * @param e the action event. */ @Override public void actionPerformed(ActionEvent e) { double delta = this.panel.getRotateIncrement(); this.panel.getViewPoint().moveUpDown(delta); this.panel.repaint(); } } orson-charts-2.1.0/src/main/java/org/jfree/chart3d/graphics3d/swing/ZoomInAction.java000066400000000000000000000100111417331271500303710ustar00rootroot00000000000000/* =========================================================== * Orson Charts : a 3D chart library for the Java(tm) platform * =========================================================== * * (C)opyright 2013-2022, by David Gilbert. All rights reserved. * * https://github.com/jfree/orson-charts * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . * * [Oracle and Java are registered trademarks of Oracle and/or its affiliates. * Other names may be trademarks of their respective owners.] * * If you do not wish to be bound by the terms of the GPL, an alternative * commercial license can be purchased. For details, please see visit the * Orson Charts home page: * * http://www.object-refinery.com/orsoncharts/index.html * */ package org.jfree.chart3d.graphics3d.swing; import java.awt.event.ActionEvent; import javax.swing.AbstractAction; import javax.swing.Action; import org.jfree.chart3d.Resources; import org.jfree.chart3d.graphics3d.ViewPoint3D; import org.jfree.chart3d.internal.Args; /** * An action that performs a zoom-in operation. *

* NOTE: This class is serializable, but the serialization format is subject * to change in future releases and should not be relied upon for persisting * instances of this class. * * @see ZoomOutAction */ @SuppressWarnings("serial") public class ZoomInAction extends AbstractAction { /** The panel that the action applies to. */ private Panel3D panel; private double zoomMultiplier; /** * Creates a new zoom-in action associated with the specified panel. * * @param panel the panel ({@code null} not permitted). * @param fontAwesome if {@code true} an icon from Font Awesome is * used for the action label, otherwise a regular text label is used. */ public ZoomInAction(Panel3D panel, boolean fontAwesome) { super("\uf00e"); Args.nullNotPermitted(panel, "panel"); this.panel = panel; this.zoomMultiplier = 0.95; if (!fontAwesome) { putValue(Action.NAME, Resources.localString("ZOOM_IN")); } putValue(Action.ACTION_COMMAND_KEY, "ZOOM_IN"); putValue(Action.SHORT_DESCRIPTION, Resources.localString("ZOOM_IN")); } /** * Returns the zoom multiplier. The default value is {@code 95 / 100} * (the inverse of the multiplier in the {@link ZoomOutAction}). * * @return The zoom multiplier. * * @since 1.3 */ public double getZoomMultiplier() { return zoomMultiplier; } /** * Sets the zoom multiplier (the current viewing distance is multiplied * by this factor to determine the new viewing distance). * * @param multiplier the new multiplier. * * @since 1.3 */ public void setZoomMultiplier(double multiplier) { this.zoomMultiplier = multiplier; } /** * Performs the zoom in action. * * @param e the action event. */ @Override public void actionPerformed(ActionEvent e) { ViewPoint3D viewPt = this.panel.getViewPoint(); double minDistance = this.panel.getMinViewingDistance(); double maxDistance = minDistance * this.panel.getMaxViewingDistanceMultiplier(); double valRho = Math.max(minDistance, Math.min(maxDistance, viewPt.getRho() * this.zoomMultiplier)); this.panel.getViewPoint().setRho(valRho); this.panel.repaint(); } } orson-charts-2.1.0/src/main/java/org/jfree/chart3d/graphics3d/swing/ZoomOutAction.java000066400000000000000000000077371417331271500306170ustar00rootroot00000000000000/* =========================================================== * Orson Charts : a 3D chart library for the Java(tm) platform * =========================================================== * * (C)opyright 2013-2022, by David Gilbert. All rights reserved. * * https://github.com/jfree/orson-charts * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . * * [Oracle and Java are registered trademarks of Oracle and/or its affiliates. * Other names may be trademarks of their respective owners.] * * If you do not wish to be bound by the terms of the GPL, an alternative * commercial license can be purchased. For details, please see visit the * Orson Charts home page: * * http://www.object-refinery.com/orsoncharts/index.html * */ package org.jfree.chart3d.graphics3d.swing; import java.awt.event.ActionEvent; import javax.swing.AbstractAction; import javax.swing.Action; import org.jfree.chart3d.Resources; import org.jfree.chart3d.graphics3d.ViewPoint3D; /** * An action that performs a zoom out operation on the content in a * {@link Panel3D}. *

* NOTE: This class is serializable, but the serialization format is subject * to change in future releases and should not be relied upon for persisting * instances of this class. * * @see ZoomInAction */ @SuppressWarnings("serial") public class ZoomOutAction extends AbstractAction { /** The panel that the action applies to. */ private final Panel3D panel; /** The multiplier used to calculate the new viewing distance. */ private double zoomMultiplier; /** * Creates a new zoom-out action associated with the specified panel. * * @param panel the panel ({@code null} not permitted). * @param fontAwesome use the FontAwesome icon text? */ public ZoomOutAction(Panel3D panel, boolean fontAwesome) { super("\uf010"); this.panel = panel; this.zoomMultiplier = 10.0 / 9.5; if (!fontAwesome) { putValue(Action.NAME, Resources.localString("ZOOM_OUT")); } putValue(Action.ACTION_COMMAND_KEY, "ZOOM_OUT"); putValue(Action.SHORT_DESCRIPTION, Resources.localString("ZOOM_OUT")); } /** * Returns the zoom multiplier. The default value is * {@code 100 / 95} (the inverse of the multiplier in the * {@link ZoomInAction}). * * @return The zoom multiplier. * * @since 1.3 */ public double getZoomMultiplier() { return zoomMultiplier; } /** * Sets the zoom multiplier (the current viewing distance is multiplied * by this factor to determine the new viewing distance). * * @param multiplier the new multiplier. * * @since 1.3 */ public void setZoomMultiplier(double multiplier) { this.zoomMultiplier = multiplier; } /** * Performs the zoom out action. * * @param e the action event. */ @Override public void actionPerformed(ActionEvent e) { ViewPoint3D viewPt = this.panel.getViewPoint(); double minDistance = this.panel.getMinViewingDistance(); double maxDistance = minDistance * this.panel.getMaxViewingDistanceMultiplier(); double valRho = Math.max(minDistance, Math.min(maxDistance, viewPt.getRho() * this.zoomMultiplier)); this.panel.getViewPoint().setRho(valRho); this.panel.repaint(); } } orson-charts-2.1.0/src/main/java/org/jfree/chart3d/graphics3d/swing/ZoomToFitAction.java000066400000000000000000000054031417331271500310610ustar00rootroot00000000000000/* =========================================================== * Orson Charts : a 3D chart library for the Java(tm) platform * =========================================================== * * (C)opyright 2013-2022, by David Gilbert. All rights reserved. * * https://github.com/jfree/orson-charts * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . * * [Oracle and Java are registered trademarks of Oracle and/or its affiliates. * Other names may be trademarks of their respective owners.] * * If you do not wish to be bound by the terms of the GPL, an alternative * commercial license can be purchased. For details, please see visit the * Orson Charts home page: * * http://www.object-refinery.com/orsoncharts/index.html * */ package org.jfree.chart3d.graphics3d.swing; import java.awt.event.ActionEvent; import javax.swing.AbstractAction; import javax.swing.Action; import org.jfree.chart3d.Resources; import org.jfree.chart3d.internal.Args; /** * An action that performs a zoom-to-fit operation. *

* NOTE: This class is serializable, but the serialization format is subject * to change in future releases and should not be relied upon for persisting * instances of this class. */ @SuppressWarnings("serial") public class ZoomToFitAction extends AbstractAction { /** The panel that the action applies to. */ private final Panel3D panel; /** * Creates a new action associated with the specified panel. * * @param panel the panel ({@code null} not permitted). * @param fontAwesome use icon? */ public ZoomToFitAction(Panel3D panel, boolean fontAwesome) { super("\uf065"); Args.nullNotPermitted(panel, "panel"); this.panel = panel; if (!fontAwesome) { putValue(Action.NAME, Resources.localString("ZOOM_TO_FIT")); } putValue(Action.ACTION_COMMAND_KEY, "ZOOM_TO_FIT"); putValue(Action.SHORT_DESCRIPTION, Resources.localString("ZOOM_TO_FIT")); } /** * Performs the zoom to fit action. * * @param e the action event. */ @Override public void actionPerformed(ActionEvent e) { this.panel.zoomToFit(); } } orson-charts-2.1.0/src/main/java/org/jfree/chart3d/graphics3d/swing/package-info.java000066400000000000000000000003361417331271500303550ustar00rootroot00000000000000/** * Components to display 3D graphics in Swing applications. This package * provides general purpose facilities, you should not find any chart-specific * code in here. */ package org.jfree.chart3d.graphics3d.swing; orson-charts-2.1.0/src/main/java/org/jfree/chart3d/interaction/000077500000000000000000000000001417331271500243255ustar00rootroot00000000000000orson-charts-2.1.0/src/main/java/org/jfree/chart3d/interaction/Chart3DMouseEvent.java000066400000000000000000000063611417331271500304410ustar00rootroot00000000000000/* =========================================================== * Orson Charts : a 3D chart library for the Java(tm) platform * =========================================================== * * (C)opyright 2013-2022, by David Gilbert. All rights reserved. * * https://github.com/jfree/orson-charts * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . * * [Oracle and Java are registered trademarks of Oracle and/or its affiliates. * Other names may be trademarks of their respective owners.] * * If you do not wish to be bound by the terms of the GPL, an alternative * commercial license can be purchased. For details, please see visit the * Orson Charts home page: * * http://www.object-refinery.com/orsoncharts/index.html * */ package org.jfree.chart3d.interaction; import java.awt.event.MouseEvent; import java.io.Serializable; import java.util.EventObject; import org.jfree.chart3d.Chart3D; import org.jfree.chart3d.Chart3DPanel; import org.jfree.chart3d.graphics3d.RenderedElement; /** * A mouse event for a chart that is displayed in a {@link Chart3DPanel}. * * @see Chart3DMouseListener * * @since 1.3 */ public class Chart3DMouseEvent extends EventObject implements Serializable { /** The chart that the mouse event relates to. */ private final Chart3D chart; /** The Java mouse event that triggered this event. */ private final MouseEvent trigger; /** The chart element (if any). */ private final RenderedElement element; /** * Constructs a new event. * * @param chart the source chart ({@code null} not permitted). * @param trigger the mouse event that triggered this event * ({@code null} not permitted). * @param element the element (if any) under the mouse pointer * ({@code null} permitted). */ public Chart3DMouseEvent(Chart3D chart, MouseEvent trigger, RenderedElement element) { super(chart); this.chart = chart; this.trigger = trigger; this.element = element; } /** * Returns the chart that the mouse event relates to. * * @return The chart (never {@code null}). */ public Chart3D getChart() { return this.chart; } /** * Returns the mouse event that triggered this event. * * @return The event (never {@code null}). */ public MouseEvent getTrigger() { return this.trigger; } /** * Returns the interactive element (if any) under the mouse point. * * @return The chart entity (possibly {@code null}). */ public RenderedElement getElement() { return this.element; } } orson-charts-2.1.0/src/main/java/org/jfree/chart3d/interaction/Chart3DMouseListener.java000066400000000000000000000042511417331271500311410ustar00rootroot00000000000000/* =========================================================== * Orson Charts : a 3D chart library for the Java(tm) platform * =========================================================== * * (C)opyright 2013-2022, by David Gilbert. All rights reserved. * * https://github.com/jfree/orson-charts * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . * * [Oracle and Java are registered trademarks of Oracle and/or its affiliates. * Other names may be trademarks of their respective owners.] * * If you do not wish to be bound by the terms of the GPL, an alternative * commercial license can be purchased. For details, please see visit the * Orson Charts home page: * * http://www.object-refinery.com/orsoncharts/index.html * */ package org.jfree.chart3d.interaction; import java.util.EventListener; import org.jfree.chart3d.Chart3DPanel; /** * The interface that must be implemented by classes that wish to receive * {@link Chart3DMouseEvent} notifications from a {@link Chart3DPanel}. * * @see Chart3DPanel#addChartMouseListener(org.jfree.chart3d.interaction.Chart3DMouseListener) * * @since 1.3 */ public interface Chart3DMouseListener extends EventListener { /** * Callback method for receiving notification of a mouse click on a chart. * * @param event information about the event. */ void chartMouseClicked(Chart3DMouseEvent event); /** * Callback method for receiving notification of a mouse movement on a * chart. * * @param event information about the event. */ void chartMouseMoved(Chart3DMouseEvent event); }orson-charts-2.1.0/src/main/java/org/jfree/chart3d/interaction/InteractiveElementType.java000066400000000000000000000051021417331271500316170ustar00rootroot00000000000000/* =========================================================== * Orson Charts : a 3D chart library for the Java(tm) platform * =========================================================== * * (C)opyright 2013-2022, by David Gilbert. All rights reserved. * * https://github.com/jfree/orson-charts * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . * * [Oracle and Java are registered trademarks of Oracle and/or its affiliates. * Other names may be trademarks of their respective owners.] * * If you do not wish to be bound by the terms of the GPL, an alternative * commercial license can be purchased. For details, please see visit the * Orson Charts home page: * * http://www.object-refinery.com/orsoncharts/index.html * */ package org.jfree.chart3d.interaction; import org.jfree.chart3d.graphics3d.RenderedElement; /** * The type for an interactive chart element. These values are used when * constructing a {@link RenderedElement}. For each type, some additional * properties will usually be defined: * *
    *
  • CATEGORY_AXIS_TICK_LABEL: 'label' (a string containing the tick label, * and 'axis' (either 'row' or 'column');
  • *
  • LEGEND_ITEM: 'series_key' (the series key)
  • *
* */ public enum InteractiveElementType { /** A data item within a chart. */ DATA_ITEM, /** The chart title. */ TITLE, /** The chart subtitle. */ SUBTITLE, /** A gridline in the chart. */ GRIDLINE, /** An axis label (the main label for an axis, not a tick label). */ AXIS_LABEL, /** A category axis tick label. */ CATEGORY_AXIS_TICK_LABEL, /** A value axis tick label. */ VALUE_AXIS_TICK_LABEL, /** The section label for a pie chart. */ SECTION_LABEL, /** The legend (see also {@link #LEGEND_ITEM}). */ LEGEND, /** * An item within a legend (typically representing a series in the chart). */ LEGEND_ITEM, /** A marker. */ MARKER } orson-charts-2.1.0/src/main/java/org/jfree/chart3d/interaction/KeyedValues3DItemSelection.java000066400000000000000000000036331417331271500322720ustar00rootroot00000000000000/* =========================================================== * Orson Charts : a 3D chart library for the Java(tm) platform * =========================================================== * * (C)opyright 2013-2022, by David Gilbert. All rights reserved. * * https://github.com/jfree/orson-charts * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . * * [Oracle and Java are registered trademarks of Oracle and/or its affiliates. * Other names may be trademarks of their respective owners.] * * If you do not wish to be bound by the terms of the GPL, an alternative * commercial license can be purchased. For details, please see visit the * Orson Charts home page: * * http://www.object-refinery.com/orsoncharts/index.html * */ package org.jfree.chart3d.interaction; import org.jfree.chart3d.data.KeyedValues3D; import org.jfree.chart3d.data.KeyedValues3DItemKey; /** * An object representing a set of selected items for a {@link KeyedValues3D} * dataset. * * @since 1.3 */ public interface KeyedValues3DItemSelection { /** * Returns {@code true} if the specified key exists in the selection, * and {@code false} otherwise. * * @param itemKey the item key ({@code null} not permitted). * * @return A boolean. */ boolean isSelected(KeyedValues3DItemKey itemKey); } StandardKeyedValues3DItemSelection.java000066400000000000000000000105651417331271500336760ustar00rootroot00000000000000orson-charts-2.1.0/src/main/java/org/jfree/chart3d/interaction/* =========================================================== * Orson Charts : a 3D chart library for the Java(tm) platform * =========================================================== * * (C)opyright 2013-2022, by David Gilbert. All rights reserved. * * https://github.com/jfree/orson-charts * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . * * [Oracle and Java are registered trademarks of Oracle and/or its affiliates. * Other names may be trademarks of their respective owners.] * * If you do not wish to be bound by the terms of the GPL, an alternative * commercial license can be purchased. For details, please see visit the * Orson Charts home page: * * http://www.object-refinery.com/orsoncharts/index.html * */ package org.jfree.chart3d.interaction; import java.io.Serializable; import java.util.Collection; import java.util.Set; import java.util.TreeSet; import org.jfree.chart3d.data.KeyedValues3D; import org.jfree.chart3d.data.KeyedValues3DItemKey; import org.jfree.chart3d.internal.Args; /** * An object that tracks selected items from a {@link KeyedValues3D} dataset. * * @since 1.3 */ public class StandardKeyedValues3DItemSelection implements KeyedValues3DItemSelection, Serializable { /** The set of selected items. */ Set selectedItems; /** * Creates a new item selection instance, initially with no selections. */ public StandardKeyedValues3DItemSelection() { this.selectedItems = new TreeSet<>(); } /** * Adds an item to the selection, returning {@code true} if the item * is added and {@code false} if the item already existed in the * selection. * * @param itemKey the item key ({@code null} not permitted). * * @return A boolean. */ public boolean add(KeyedValues3DItemKey itemKey) { Args.nullNotPermitted(itemKey, "itemKey"); return this.selectedItems.add(itemKey); } /** * Adds a collection of items to the selection, returning {@code true} * if the selection is changed, and {@code false} if no changes were * made. * * @param keys the keys to add ({@code null} not permitted). * * @return A boolean. */ public boolean addAll(Collection keys) { Args.nullNotPermitted(keys, "keys"); return this.selectedItems.addAll(keys); } /** * Removes an item from the selection returning {@code true} if the * item was removed and {@code false} if it did not exist within the * selection. * * @param itemKey the item key ({@code null} not permitted). * * @return A boolean. */ public boolean remove(KeyedValues3DItemKey itemKey) { return this.selectedItems.remove(itemKey); } /** * Returns {@code true} if the specified item is in the selection, * and {@code false} otherwise. * * @param itemKey the item key ({@code null} not permitted). * * @return A boolean. */ @Override public boolean isSelected(KeyedValues3DItemKey itemKey) { return this.selectedItems.contains(itemKey); } /** * Clears the item selection (that is, removes all items contained in the * selection). */ public void clear() { this.selectedItems.clear(); } @Override public boolean equals(Object obj) { if (obj == this) { return true; } if (!(obj instanceof StandardKeyedValues3DItemSelection)) { return false; } StandardKeyedValues3DItemSelection that = (StandardKeyedValues3DItemSelection) obj; if (!this.selectedItems.equals(that.selectedItems)) { return false; } return true; } } orson-charts-2.1.0/src/main/java/org/jfree/chart3d/interaction/StandardXYZDataItemSelection.java000066400000000000000000000072741417331271500326340ustar00rootroot00000000000000/* =========================================================== * Orson Charts : a 3D chart library for the Java(tm) platform * =========================================================== * * (C)opyright 2013-2022, by David Gilbert. All rights reserved. * * https://github.com/jfree/orson-charts * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . * * [Oracle and Java are registered trademarks of Oracle and/or its affiliates. * Other names may be trademarks of their respective owners.] * * If you do not wish to be bound by the terms of the GPL, an alternative * commercial license can be purchased. For details, please see visit the * Orson Charts home page: * * http://www.object-refinery.com/orsoncharts/index.html * */ package org.jfree.chart3d.interaction; import java.util.Set; import java.util.TreeSet; import java.util.Collection; import org.jfree.chart3d.data.xyz.XYZDataset; import org.jfree.chart3d.data.xyz.XYZItemKey; import org.jfree.chart3d.internal.Args; /** * An object that tracks selected items from an {@link XYZDataset}. * * @param S * * @since 1.3 */ public class StandardXYZDataItemSelection implements XYZDataItemSelection { /** The selected items. */ Set selectedItems; /** * Creates a new (empty) selection. */ public StandardXYZDataItemSelection() { this.selectedItems = new TreeSet<>(); } /** * Adds an item to the selection, returns {@code true} if the item * was added and {@code false} if it already existed in the selection. * * @param item the item key ({@code null} not permitted). * * @return A boolean. */ public boolean add(XYZItemKey item) { Args.nullNotPermitted(item, "item"); return this.selectedItems.add(item); } /** * Adds all the items from the specified collection, returning * {@code true} if the selection is updated or {@code false} if * all the supplied keys are already present in the selection. * * @param keys the keys ({@code null} not permitted). * * @return A boolean. */ public boolean addAll(Collection keys) { Args.nullNotPermitted(keys, "keys"); return this.selectedItems.addAll(keys); } /** * Removes an item from the selection, returning {@code true} if the * item was removed and {@code false} if it was not present in the * selection. * * @param item the item ({@code null} not permitted). * * @return A boolean. */ public boolean remove(XYZItemKey item) { return this.selectedItems.remove(item); } /** * Returns {@code true} if the item is present in the selection, * and {@code false} otherwise. * * @param item the item {@code null} not permitted). * * @return A boolean. */ @Override public boolean isSelected(XYZItemKey item) { return this.selectedItems.contains(item); } /** * Clears the selection. */ public void clear() { this.selectedItems.clear(); } } orson-charts-2.1.0/src/main/java/org/jfree/chart3d/interaction/XYZDataItemSelection.java000066400000000000000000000036001417331271500311400ustar00rootroot00000000000000/* =========================================================== * Orson Charts : a 3D chart library for the Java(tm) platform * =========================================================== * * (C)opyright 2013-2022, by David Gilbert. All rights reserved. * * https://github.com/jfree/orson-charts * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . * * [Oracle and Java are registered trademarks of Oracle and/or its affiliates. * Other names may be trademarks of their respective owners.] * * If you do not wish to be bound by the terms of the GPL, an alternative * commercial license can be purchased. For details, please see visit the * Orson Charts home page: * * http://www.object-refinery.com/orsoncharts/index.html * */ package org.jfree.chart3d.interaction; import org.jfree.chart3d.data.xyz.XYZDataset; import org.jfree.chart3d.data.xyz.XYZItemKey; /** * An object representing a selection of items from an {@link XYZDataset}. */ public interface XYZDataItemSelection> { /** * Returns {@code true} if the specified item is present in the * selection, and {@code false} otherwise. * * @param item the item key ({@code null} not permitted). * * @return A boolean. */ boolean isSelected(XYZItemKey item); } orson-charts-2.1.0/src/main/java/org/jfree/chart3d/interaction/package-info.java000066400000000000000000000001441417331271500275130ustar00rootroot00000000000000/** * Classes that support user interaction with charts. */ package org.jfree.chart3d.interaction;orson-charts-2.1.0/src/main/java/org/jfree/chart3d/internal/000077500000000000000000000000001417331271500236225ustar00rootroot00000000000000orson-charts-2.1.0/src/main/java/org/jfree/chart3d/internal/Args.java000066400000000000000000000113461417331271500253660ustar00rootroot00000000000000/* =========================================================== * Orson Charts : a 3D chart library for the Java(tm) platform * =========================================================== * * (C)opyright 2013-2022, by David Gilbert. All rights reserved. * * https://github.com/jfree/orson-charts * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . * * [Oracle and Java are registered trademarks of Oracle and/or its affiliates. * Other names may be trademarks of their respective owners.] * * If you do not wish to be bound by the terms of the GPL, an alternative * commercial license can be purchased. For details, please see visit the * Orson Charts home page: * * http://www.object-refinery.com/orsoncharts/index.html * */ package org.jfree.chart3d.internal; /** * Utility methods for argument checking. Throughout Orson Charts, arguments * passed to methods are validated and exceptions thrown for invalid cases * (the idea is to fail fast, which usually helps when tracking down errors * in programming logic). */ public final class Args { private Args() { // no need to instantiate this ever } /** * Checks if the specified argument is {@code null} and, if it is, * throws an {@code IllegalArgumentException}. * * @param arg the argument to check ({@code null} permitted). * @param name the parameter name ({@code null} not permitted). */ public static void nullNotPermitted(Object arg, String name) { if (arg == null) { throw new IllegalArgumentException("Null '" + name + "' argument."); } } /** * Checks if the specified argument is negative and, if it is, throws an * {@code IllegalArgumentException}. * * @param value the value. * @param name the parameter name ({@code null} not permitted). */ public static void negativeNotPermitted(double value, String name) { if (value < 0.0) { throw new IllegalArgumentException("Param '" + name + "' cannot be negative"); } } /** * Checks if the specified argument is positive and, if it is NOT, throws an * {@code IllegalArgumentException}. * * @param value the value. * @param name the parameter name ({@code null} not permitted). */ public static void positiveRequired(double value, String name) { if (value <= 0.0) { throw new IllegalArgumentException("Param '" + name + "' must be positive."); } } /** * Checks if the specified argument is finite and, if it is NOT, throws an * {@code IllegalArgumentException}. * * @param value the value. * @param name the parameter name ({@code null} not permitted). * * @since 1.4 */ public static void finiteRequired(double value, String name) { if (Double.isInfinite(value)) { throw new IllegalArgumentException("Param '" + name + "' must be finite."); } } /** * Checks if the specified argument is finite and positive and, * if it is NOT, throws an {@code IllegalArgumentException}. * * @param value the value. * @param name the parameter name ({@code null} not permitted). * * @since 1.4 */ public static void finitePositiveRequired(double value, String name) { if (value <= 0.0 || Double.isInfinite(value)) { throw new IllegalArgumentException("Param '" + name + "' must be finite and positive."); } } /** * Checks that the index is less than the specified {@code arrayLimit} * and throws an {@code IllegalArgumentException} if it is not. * * @param index the array index. * @param name the parameter name (to display in the error message). * @param arrayLimit the array size. */ public static void checkArrayBounds(int index, String name, int arrayLimit) { if (index >= arrayLimit) { throw new IllegalArgumentException("Requires '" + name + "' in the range 0 to " + (arrayLimit - 1)); } } } orson-charts-2.1.0/src/main/java/org/jfree/chart3d/internal/ChartBox3D.java000066400000000000000000001303011417331271500263640ustar00rootroot00000000000000/* =========================================================== * Orson Charts : a 3D chart library for the Java(tm) platform * =========================================================== * * (C)opyright 2013-2022, by David Gilbert. All rights reserved. * * https://github.com/jfree/orson-charts * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . * * [Oracle and Java are registered trademarks of Oracle and/or its affiliates. * Other names may be trademarks of their respective owners.] * * If you do not wish to be bound by the terms of the GPL, an alternative * commercial license can be purchased. For details, please see visit the * Orson Charts home page: * * http://www.object-refinery.com/orsoncharts/index.html * */ package org.jfree.chart3d.internal; import java.awt.Color; import java.awt.geom.Point2D; import java.util.ArrayList; import java.util.Collections; import java.util.List; import org.jfree.chart3d.axis.TickData; import org.jfree.chart3d.graphics2d.Anchor2D; import org.jfree.chart3d.graphics3d.Face; import org.jfree.chart3d.graphics3d.Object3D; import org.jfree.chart3d.graphics3d.Point3D; import org.jfree.chart3d.marker.MarkerData; import org.jfree.chart3d.marker.MarkerDataType; /** * A chart box is the container within which the chart elements are drawn. * The six faces of the box created so that they are visible only when they * do not obscure the content of the chart (generally the back three faces * will be visible and the front three faces will not be visible, although from * some angles four faces will be visible at one time). There is also support * provided for specifying gridlines on the visible faces, as well as markers * to label specific values and value ranges. */ public class ChartBox3D { private double xLength, yLength, zLength; private double xOffset, yOffset, zOffset; /** * Tick info for the x-axis (or column axis). */ private List xTicks; /** * Tick info for the y-axis (or value axis). */ private List yTicks; /** * Tick info for the z-axis (or row axis). */ private List zTicks; /** * Incoming data for x-axis markers. New instances are created and * assigned to chart box faces to track vertices. */ private List xMarkers; /** Required data for y-axis markers. */ private List yMarkers; /** Required data for z-axis markers. */ private List zMarkers; private final Color color; private ChartBoxFace faceA; private ChartBoxFace faceB; private ChartBoxFace faceC; private ChartBoxFace faceD; private ChartBoxFace faceE; private ChartBoxFace faceF; /** * Creates a new chart box with the specified attributes. When drawn, only * the faces at the rear of the box will be rendered, allowing the user to * see the content of the box (typically the plot items). * * @param xLength the x-dimension. * @param yLength the y-dimension. * @param zLength the z-dimension. * @param xOffset the x-offset. * @param yOffset the y-offset. * @param zOffset the z-offset. * @param color the color for the sides of the box ({@code null} not * permitted). */ public ChartBox3D(double xLength, double yLength, double zLength, double xOffset, double yOffset, double zOffset, Color color) { Args.nullNotPermitted(color, "color"); this.xLength = xLength; this.yLength = yLength; this.zLength = zLength; this.xOffset = xOffset; this.yOffset = yOffset; this.zOffset = zOffset; this.color = color; this.xTicks = new ArrayList<>(0); this.yTicks = new ArrayList<>(0); this.zTicks = new ArrayList<>(0); this.xMarkers = new ArrayList<>(0); this.yMarkers = new ArrayList<>(0); this.zMarkers = new ArrayList<>(0); } /** * Returns the list of tick data items for the x-axis. * * @return The list of tick data items for the x-axis (possibly empty, but * never {@code null}). * * @since 1.2 */ public List getXTicks() { return this.xTicks; } /** * Sets the list of tick data items for the x-axis. * * @param ticks the tick data ({@code null} not permitted). * * @since 1.2 */ public void setXTicks(List ticks) { Args.nullNotPermitted(ticks, "ticks"); this.xTicks = ticks; } /** * Returns the list of tick data items for the y-axis. * * @return The list of tick data items for the y-axis (possibly empty, but * never {@code null}). * * @since 1.2 */ public List getYTicks() { return this.yTicks; } /** * Sets the list of tick data items for the y-axis. * * @param ticks the tick data ({@code null} not permitted). * * @since 1.2 */ public void setYTicks(List ticks) { Args.nullNotPermitted(ticks, "ticks"); this.yTicks = ticks; } /** * Returns the list of tick data items for the z-axis. * * @return The list of tick data items for the z-axis (possibly empty, but * never {@code null}). * * @since 1.2 */ public List getZTicks() { return this.zTicks; } /** * Sets the list of tick data items for the z-axis. * * @param ticks the tick data ({@code null} not permitted). * * @since 1.2 */ public void setZTicks(List ticks) { Args.nullNotPermitted(ticks, "ticks"); this.zTicks = ticks; } /** * Returns the marker data for the x-axis markers, if any. * * @return The marker data for the x-axis markers (possibly empty but * never {@code null}). * * @since 1.2 */ public List getXMarkers() { return this.xMarkers; } /** * Sets the list of marker data items for the x-axis. * * @param markers the list of marker data items ({@code null} not * permitted). * * @since 1.2 */ public void setXMarkers(List markers) { Args.nullNotPermitted(markers, "markers"); this.xMarkers = markers; } /** * Returns the marker data for the y-axis markers, if any. * * @return The marker data for the y-axis markers (possibly empty but * never {@code null}). * * @since 1.2 */ public List getYMarkers() { return this.yMarkers; } /** * Sets the list of marker data items for the y-axis. * * @param markers the list of marker data items ({@code null} not * permitted). * * @since 1.2 */ public void setYMarkers(List markers) { Args.nullNotPermitted(markers, "markers"); this.yMarkers = markers; } /** * Returns the marker data for the z-axis markers, if any. * * @return The marker data for the z-axis markers (possibly empty but * never {@code null}). * * @since 1.2 */ public List getZMarkers() { return this.zMarkers; } /** * Sets the list of marker data items for the x-axis. * * @param markers the list of marker data items ({@code null} not * permitted). * * @since 1.2 */ public void setZMarkers(List markers) { Args.nullNotPermitted(markers, "markers"); this.zMarkers = markers; } /** * Returns face A (the bottom face, in the XZ axis plane). * * @return Face A. */ public ChartBoxFace faceA() { return this.faceA; } /** * Returns face B (the front face, in the XY axis plane). * * @return Face B. */ public ChartBoxFace faceB() { return this.faceB; } /** * Returns face C (the top face, in the XZ axis plane). * * @return Face C. */ public ChartBoxFace faceC() { return this.faceC; } /** * Returns face D (the rear face, in the XY axis plane). * * @return Face D. */ public ChartBoxFace faceD() { return this.faceD; } /** * Returns face E (the left face, in the YZ axis plane). * * @return Face E. */ public ChartBoxFace faceE() { return this.faceE; } /** * Returns face F (the right face, in the YZ axis plane). * * @return Face F. */ public ChartBoxFace faceF() { return this.faceF; } /** * Creates an {@link Object3D} that contains the six faces for the * chart box, plus the vertices for the tick marks along the edges of * each face. * * @return A 3D object. */ public Object3D createObject3D() { Object3D box = new Object3D(this.color); Point3D v0 = new Point3D(xOffset, yOffset, zOffset); Point3D v1 = new Point3D(xLength + xOffset, yOffset, zOffset); Point3D v2 = new Point3D(xLength + xOffset, yLength + yOffset, zOffset); Point3D v3 = new Point3D(xOffset, yLength + yOffset, zOffset); Point3D v4 = new Point3D(xOffset, yLength + yOffset, zLength + zOffset); Point3D v5 = new Point3D(xOffset, yOffset, zLength + zOffset); Point3D v6 = new Point3D(xLength + xOffset, yOffset, zLength + zOffset); Point3D v7 = new Point3D(xLength + xOffset, yLength + yOffset, zLength + zOffset); box.addVertex(v0); // 0, 0, 0 box.addVertex(v1); // 1, 0, 0 box.addVertex(v2); // 1, 1, 0 box.addVertex(v3); // 0, 1, 0 box.addVertex(v4); // 0, 1, 1 box.addVertex(v5); // 0, 0, 1 box.addVertex(v6); // 1, 0, 1 box.addVertex(v7); // 1, 1, 1 this.faceA = new ChartBoxFace(box, new int[] {0, 5, 6, 1}); // XZ this.faceB = new ChartBoxFace(box, new int[] {0, 1, 2, 3}); // XY this.faceC = new ChartBoxFace(box, new int[] {7, 4, 3, 2}); // XZ this.faceD = new ChartBoxFace(box, new int[] {5, 4, 7, 6}); // XY this.faceE = new ChartBoxFace(box, new int[] {0, 3, 4, 5}); // YZ this.faceF = new ChartBoxFace(box, new int[] {6, 7, 2, 1}); // YZ box.addFace(faceA); box.addFace(faceB); box.addFace(faceC); box.addFace(faceD); box.addFace(faceE); box.addFace(faceF); // add vertices for the x-grid lines (ABCD) int base = 8; for (TickData t : this.xTicks) { double xx = this.xOffset + this.xLength * t.getPos(); box.addVertex(xx, yOffset, zOffset); box.addVertex(xx, yOffset, zOffset + zLength); box.addVertex(xx, yOffset + yLength, zOffset + zLength); box.addVertex(xx, yOffset + yLength, zOffset); TickData td0 = new TickData(t, base); TickData td1 = new TickData(t, base + 1); TickData td2 = new TickData(t, base + 2); TickData td3 = new TickData(t, base + 3); this.faceA.addXTicks(td0, td1); this.faceB.addXTicks(td0, td3); this.faceC.addXTicks(td3, td2); this.faceD.addXTicks(td2, td1); base += 4; } // add vertices for the y-grid lines (BDEF) for (TickData t : this.yTicks) { double yy = this.yOffset + this.yLength * t.getPos(); box.addVertex(xOffset, yy, zOffset); box.addVertex(xOffset + xLength, yy, zOffset); box.addVertex(xOffset + xLength, yy, zOffset + zLength); box.addVertex(xOffset, yy, zOffset + zLength); TickData td0 = new TickData(t, base); TickData td1 = new TickData(t, base + 1); TickData td2 = new TickData(t, base + 2); TickData td3 = new TickData(t, base + 3); this.faceB.addYTicks(td0, td1); this.faceD.addYTicks(td2, td3); this.faceE.addYTicks(td0, td3); this.faceF.addYTicks(td1, td2); base += 4; } // add vertices for the z-grid lines (ACEF) for (TickData t : this.zTicks) { double zz = this.zOffset + this.zLength * t.getPos(); box.addVertex(xOffset, yOffset, zz); box.addVertex(xOffset + xLength, yOffset, zz); box.addVertex(xOffset + xLength, yOffset + yLength, zz); box.addVertex(xOffset, yOffset + yLength, zz); TickData td0 = new TickData(t, base); TickData td1 = new TickData(t, base + 1); TickData td2 = new TickData(t, base + 2); TickData td3 = new TickData(t, base + 3); this.faceA.addZTicks(td0, td1); this.faceC.addZTicks(td3, td2); this.faceE.addZTicks(td0, td3); this.faceF.addZTicks(td1, td2); base += 4; } // add vertices for the x-markers for (MarkerData m : this.xMarkers) { if (m.getType().equals(MarkerDataType.VALUE)) { double xpos = this.xOffset + xLength * m.getValueLine().getPos(); base += addXMarker(box, m, xpos, base); } else if (m.getType().equals(MarkerDataType.RANGE)) { double startX = this.xOffset + xLength * m.getStartLine().getPos(); double endX = this.xOffset + xLength * m.getEndLine().getPos(); base += addXRangeMarker(box, m, startX, endX, base); } } // add vertices for the y-markers for (MarkerData m : this.yMarkers) { if (m.getType().equals(MarkerDataType.VALUE)) { double ypos = this.yOffset + yLength * m.getValueLine().getPos(); base += addYMarker(box, m, ypos, base); } else if (m.getType().equals(MarkerDataType.RANGE)) { double startY = this.yOffset + yLength * m.getStartLine().getPos(); double endY = this.yOffset + yLength * m.getEndLine().getPos(); base += addYRangeMarker(box, m, startY, endY, base); } } // add vertices for the z-markers for (MarkerData m : this.zMarkers) { if (m.getType().equals(MarkerDataType.VALUE)) { double zpos = this.zOffset + zLength * m.getValueLine().getPos(); base += addZMarker(box, m, zpos, base); } else if (m.getType().equals(MarkerDataType.RANGE)) { double startZ = this.zOffset + zLength * m.getStartLine().getPos(); double endZ = this.zOffset + zLength * m.getEndLine().getPos(); base += addZRangeMarker(box, m, startZ, endZ, base); } } return box; } /** * Adds the vertices required for an x-marker (VALUE type), creates the * marker data records and adds them to the four faces that will be * required to draw the marker. If there is a label for the marker, this * method will also add vertices to track the label anchor points. * * @param box the chart box. * @param m the marker data record. * @param x the x position for the marker. * @param base the base vertex index. */ private int addXMarker(Object3D box, MarkerData m, double x, int base) { int result = 4; Point3D v0 = new Point3D(x, yOffset, zOffset); Point3D v1 = new Point3D(x, yOffset, zOffset + zLength); Point3D v2 = new Point3D(x, yOffset + yLength, zOffset + zLength); Point3D v3 = new Point3D(x, yOffset + yLength, zOffset); box.addVertex(v0); box.addVertex(v1); box.addVertex(v2); box.addVertex(v3); MarkerData md0 = new MarkerData(m, base, base + 1); // A MarkerData md1 = new MarkerData(m, base + 1, base + 2); // D MarkerData md2 = new MarkerData(m, base + 2, base + 3); // C MarkerData md3 = new MarkerData(m, base + 3, base); // B if (m.getLabelAnchor() != null) { // add vertices for the label anchor Point3D v4 = calcAnchorXY(m.getLabelAnchor(), v0, v3, xLength); // B Point3D v5 = calcAnchorXY(m.getLabelAnchor(), v2, v1, xLength); // D Point3D v6 = calcAnchorXZ(m.getLabelAnchor(), v1, v0, xLength); // A Point3D v7 = calcAnchorXZ(m.getLabelAnchor(), v3, v2, xLength); box.addVertex(v4); box.addVertex(v5); box.addVertex(v6); box.addVertex(v7); // now write back the label vertex indices to the marker data md3.setLabelVertexIndex(base + 4); md1.setLabelVertexIndex(base + 5); md0.setLabelVertexIndex(base + 6); md2.setLabelVertexIndex(base + 7); result += 4; } this.faceA.addXMarker(md0); this.faceD.addXMarker(md1); this.faceC.addXMarker(md2); this.faceB.addXMarker(md3); return result; } /** * Adds the vertices required for an x-marker (RANGE type), creates the * marker data records and adds them to the four faces that will be * required to draw the marker. If there is a label for the marker, this * method will also add vertices to track the label anchor points. * * @param box the chart box. * @param m the marker data record. * @param startX the starting x position for the marker. * @param endX the ending x position for the marker. * @param base the base vertex index. */ private int addXRangeMarker(Object3D box, MarkerData m, double startX, double endX, int base) { int result = 8; // number of vertices added Point3D v0 = new Point3D(startX, yOffset, zOffset); Point3D v1 = new Point3D(startX, yOffset, zOffset + zLength); Point3D v2 = new Point3D(startX, yOffset + yLength, zOffset + zLength); Point3D v3 = new Point3D(startX, yOffset + yLength, zOffset); Point3D v4 = new Point3D(endX, yOffset, zOffset); Point3D v5 = new Point3D(endX, yOffset, zOffset + zLength); Point3D v6 = new Point3D(endX, yOffset + yLength, zOffset + zLength); Point3D v7 = new Point3D(endX, yOffset + yLength, zOffset); box.addVertex(v0); box.addVertex(v1); box.addVertex(v2); box.addVertex(v3); box.addVertex(v4); box.addVertex(v5); box.addVertex(v6); box.addVertex(v7); MarkerData md0 = new MarkerData(m, base, base + 1, base + 4, base + 5); // A MarkerData md1 = new MarkerData(m, base + 1, base + 2, base + 5, base + 6); // D MarkerData md2 = new MarkerData(m, base + 2, base + 3, base + 6, base + 7); // C MarkerData md3 = new MarkerData(m, base + 3, base, base + 7, base + 4); // B if (m.getLabelAnchor() != null) { // add vertices for the label anchor Point3D v8 = calcRangeAnchorXY(m.getLabelAnchor(), v2, v1, v6, v5); Point3D v9 = calcRangeAnchorXY(m.getLabelAnchor(), v0, v3, v4, v7); Point3D v10 = calcRangeAnchorXZ(m.getLabelAnchor(), v3, v2, v7, v6); Point3D v11 = calcRangeAnchorXZ(m.getLabelAnchor(), v1, v0, v5, v4); box.addVertex(v8); box.addVertex(v9); box.addVertex(v10); box.addVertex(v11); // now write back the label vertex indices to the marker data md1.setLabelVertexIndex(base + 8); md3.setLabelVertexIndex(base + 9); md2.setLabelVertexIndex(base + 10); md0.setLabelVertexIndex(base + 11); result += 4; } this.faceA.addXMarker(md0); this.faceD.addXMarker(md1); this.faceC.addXMarker(md2); this.faceB.addXMarker(md3); return result; } /** * Adds the vertices required for an y-marker (VALUE type), creates the * marker data records and adds them to the four faces that will be * required to draw the marker. If there is a label for the marker, this * method will also add vertices to track the label anchor points. * * @param box the chart box. * @param m the marker data record. * @param y the y position for the marker. * @param base the base vertex index. */ private int addYMarker(Object3D box, MarkerData m, double y, int base) { int result = 4; // number of vertices added Point3D v0 = new Point3D(xOffset, y, zOffset); Point3D v1 = new Point3D(xOffset, y, zOffset + zLength); Point3D v2 = new Point3D(xOffset + xLength, y, zOffset + zLength); Point3D v3 = new Point3D(xOffset + xLength, y, zOffset); box.addVertex(v0); box.addVertex(v1); box.addVertex(v2); box.addVertex(v3); MarkerData md0 = new MarkerData(m, base, base + 1); // E MarkerData md1 = new MarkerData(m, base + 1, base + 2); // D MarkerData md2 = new MarkerData(m, base + 2, base + 3); // F MarkerData md3 = new MarkerData(m, base + 3, base); // B if (m.getLabelAnchor() != null) { // add vertices for the label anchor Point3D v4 = calcAnchorYX(m.getLabelAnchor(), v1, v2, yLength); // D Point3D v5 = calcAnchorYX(m.getLabelAnchor(), v3, v0, yLength); // B Point3D v6 = calcAnchorYZ(m.getLabelAnchor(), v0, v1, yLength); // E Point3D v7 = calcAnchorYZ(m.getLabelAnchor(), v2, v3, yLength); // F box.addVertex(v4); box.addVertex(v5); box.addVertex(v6); box.addVertex(v7); // now write back the label vertex indices to the marker data md1.setLabelVertexIndex(base + 4); md3.setLabelVertexIndex(base + 5); md0.setLabelVertexIndex(base + 6); md2.setLabelVertexIndex(base + 7); result += 4; } this.faceE.addYMarker(md0); this.faceD.addYMarker(md1); this.faceF.addYMarker(md2); this.faceB.addYMarker(md3); return result; } /** * Adds the vertices required for an y-marker (RANGE type), creates the * marker data records and adds them to the four faces that will be * required to draw the marker. If there is a label for the marker, this * method will also add vertices to track the label anchor points. * * @param box the chart box. * @param m the marker data record. * @param startY the starting y position for the marker. * @param endY the ending y position for the marker. * @param base the base vertex index. */ private int addYRangeMarker(Object3D box, MarkerData m, double startY, double endY, int base) { int result = 8; // number of vertices added Point3D v0 = new Point3D(xOffset, startY, zOffset); Point3D v1 = new Point3D(xOffset, startY, zOffset + zLength); Point3D v2 = new Point3D(xOffset + xLength, startY, zOffset + zLength); Point3D v3 = new Point3D(xOffset + xLength, startY, zOffset); Point3D v4 = new Point3D(xOffset, endY, zOffset); Point3D v5 = new Point3D(xOffset, endY, zOffset + zLength); Point3D v6 = new Point3D(xOffset + xLength, endY, zOffset + zLength); Point3D v7 = new Point3D(xOffset + xLength, endY, zOffset); box.addVertex(v0); box.addVertex(v1); box.addVertex(v2); box.addVertex(v3); box.addVertex(v4); box.addVertex(v5); box.addVertex(v6); box.addVertex(v7); MarkerData md0 = new MarkerData(m, base, base + 1, base + 4, base + 5); // E MarkerData md1 = new MarkerData(m, base + 1, base + 2, base + 5, base + 6); // D MarkerData md2 = new MarkerData(m, base + 2, base + 3, base + 6, base + 7); // F MarkerData md3 = new MarkerData(m, base + 3, base, base + 7, base + 4); // B if (m.getLabelAnchor() != null) { // add vertices for the label anchor Point3D v8 = calcRangeAnchorYX(m.getLabelAnchor(), v1, v2, v5, v6); Point3D v9 = calcRangeAnchorYX(m.getLabelAnchor(), v3, v0, v7, v4); Point3D v10 = calcRangeAnchorYZ(m.getLabelAnchor(), v2, v3, v6, v7); Point3D v11 = calcRangeAnchorYZ(m.getLabelAnchor(), v0, v1, v4, v5); box.addVertex(v8); box.addVertex(v9); box.addVertex(v10); box.addVertex(v11); // now write back the label vertex indices to the marker data md1.setLabelVertexIndex(base + 8); md3.setLabelVertexIndex(base + 9); md2.setLabelVertexIndex(base + 10); md0.setLabelVertexIndex(base + 11); result += 4; } this.faceE.addYMarker(md0); this.faceD.addYMarker(md1); this.faceF.addYMarker(md2); this.faceB.addYMarker(md3); return result; } /** * Adds the vertices required for an z-marker (VALUE type), creates the * marker data records and adds them to the four faces that will be * required to draw the marker. If there is a label for the marker, this * method will also add vertices to track the label anchor points. * * @param box the chart box. * @param m the marker data record. * @param z the z position for the marker. * @param base the base vertex index. */ private int addZMarker(Object3D box, MarkerData m, double z, int base) { int result = 4; // number of vertices added Point3D v0 = new Point3D(xOffset, yOffset, z); Point3D v1 = new Point3D(xOffset + xLength, yOffset, z); Point3D v2 = new Point3D(xOffset + xLength, yOffset + yLength, z); Point3D v3 = new Point3D(xOffset, yOffset + yLength, z); box.addVertex(v0); // A box.addVertex(v1); box.addVertex(v2); box.addVertex(v3); MarkerData md0 = new MarkerData(m, base, base + 1); // A MarkerData md1 = new MarkerData(m, base + 1, base + 2); // F MarkerData md2 = new MarkerData(m, base + 2, base + 3); // C MarkerData md3 = new MarkerData(m, base + 3, base); // E if (m.getLabelAnchor() != null) { // add vertices for the label anchor Point3D v4 = calcAnchorZX(m.getLabelAnchor(), v0, v1, zLength); // A Point3D v5 = calcAnchorZX(m.getLabelAnchor(), v2, v3, zLength); // C Point3D v6 = calcAnchorZY(m.getLabelAnchor(), v1, v2, zLength); // F Point3D v7 = calcAnchorZY(m.getLabelAnchor(), v3, v0, zLength); // E box.addVertex(v4); box.addVertex(v5); box.addVertex(v6); box.addVertex(v7); // now write back the label vertex indices to the marker data md0.setLabelVertexIndex(base + 4); md2.setLabelVertexIndex(base + 5); md1.setLabelVertexIndex(base + 6); md3.setLabelVertexIndex(base + 7); result += 4; } this.faceA.addZMarker(md0); this.faceF.addZMarker(md1); this.faceC.addZMarker(md2); this.faceE.addZMarker(md3); return result; } /** * Adds the vertices required for an x-marker (RANGE type), creates the * marker data records and adds them to the four faces that will be * required to draw the marker. If there is a label for the marker, this * method will also add vertices to track the label anchor points. * * @param box the chart box. * @param m the marker data record. * @param startZ the starting z position for the marker. * @param endZ the ending z position for the marker. * @param base the base vertex index. */ private int addZRangeMarker(Object3D box, MarkerData m, double startZ, double endZ, int base) { int result = 8; Point3D v0 = new Point3D(xOffset, yOffset, startZ); Point3D v1 = new Point3D(xOffset + xLength, yOffset, startZ); Point3D v2 = new Point3D(xOffset + xLength, yOffset + yLength, startZ); Point3D v3 = new Point3D(xOffset, yOffset + yLength, startZ); Point3D v4 = new Point3D(xOffset, yOffset, endZ); Point3D v5 = new Point3D(xOffset + xLength, yOffset, endZ); Point3D v6 = new Point3D(xOffset + xLength, yOffset + yLength, endZ); Point3D v7 = new Point3D(xOffset, yOffset + yLength, endZ); box.addVertex(v0); // A box.addVertex(v1); box.addVertex(v2); box.addVertex(v3); box.addVertex(v4); // A box.addVertex(v5); box.addVertex(v6); box.addVertex(v7); MarkerData md0 = new MarkerData(m, base, base + 1, base + 4, base + 5); // A MarkerData md1 = new MarkerData(m, base + 1, base + 2, base + 5, base + 6); // F MarkerData md2 = new MarkerData(m, base + 2, base + 3, base + 6, base + 7); // C MarkerData md3 = new MarkerData(m, base + 3, base, base + 7, base + 4); // E if (m.getLabelAnchor() != null) { // add vertices for the label anchor Point3D v8 = calcRangeAnchorZX(m.getLabelAnchor(), v0, v1, v4, v5); Point3D v9 = calcRangeAnchorZX(m.getLabelAnchor(), v2, v3, v6, v7); Point3D v10 = calcRangeAnchorZY(m.getLabelAnchor(), v3, v0, v7, v4); Point3D v11 = calcRangeAnchorZY(m.getLabelAnchor(), v1, v2, v5, v6); box.addVertex(v8); box.addVertex(v9); box.addVertex(v10); box.addVertex(v11); // now write back the label vertex indices to the marker data md0.setLabelVertexIndex(base + 8); md2.setLabelVertexIndex(base + 9); md3.setLabelVertexIndex(base + 10); md1.setLabelVertexIndex(base + 11); result += 4; } this.faceA.addZMarker(md0); this.faceF.addZMarker(md1); this.faceC.addZMarker(md2); this.faceE.addZMarker(md3); return result; } /** * Returns the horizontal offset for an anchor assuming that (a) the delta * is expressed as a percentage, and (b) the length in the offset direction * is {@code length}. * * @param anchor the anchor. * @param length the length. * * @return The offset. */ private double hoffset(Anchor2D anchor, double length) { double offset = 0.0; if (anchor.getRefPt().isLeft()) { offset = length * anchor.getOffset().getDX(); } else if (anchor.getRefPt().isRight()) { offset = -length * anchor.getOffset().getDX(); } return offset; } /** * Returns the vertical offset for an anchor assuming that (a) the delta is * expressed as a percentage, and (b) the length in the offset direction * is {@code length}. * * @param anchor the anchor. * @param length the length. * * @return The offset. */ private double voffset(Anchor2D anchor, double length) { double offset = 0.0; if (anchor.getRefPt().isTop()) { offset = length * anchor.getOffset().getDY(); } else if (anchor.getRefPt().isBottom()) { offset = -length * anchor.getOffset().getDY(); } return offset; } /** * Returns the horizontal position along the line based on the anchor * point. * * @param anchor the anchor ({@code null} not permitted). * @param start the start value. * @param end the end value. * * @return The position. */ private double hpos(Anchor2D anchor, double start, double end) { if (anchor.getRefPt().isLeft()) { return start; } else if (anchor.getRefPt().isRight()) { return end; } return (start + end) / 2.0; } // anchor for x-marker label where line runs parallel to y-axis private Point3D calcAnchorXY(Anchor2D anchor, Point3D start, Point3D end, double xLength) { double dx = hoffset(anchor, end.getY() - start.getY()); double dy = voffset(anchor, xLength); double y = hpos(anchor, start.getY(), end.getY()); return new Point3D(start.getX() + dy, y + dx, start.getZ()); } // anchor for x-marker label where line runs parallel to z-axis private Point3D calcAnchorXZ(Anchor2D anchor, Point3D start, Point3D end, double xLength) { double dx = hoffset(anchor, end.getZ() - start.getZ()); double dy = voffset(anchor, xLength); double z = hpos(anchor, start.getZ(), end.getZ()); return new Point3D(start.getX() + dy, start.getY(), z + dx); } // anchor for y-marker label where line runs parallel to x-axis private Point3D calcAnchorYX(Anchor2D anchor, Point3D start, Point3D end, double yLength) { double dx = hoffset(anchor, end.getX() - start.getX()); double dy = voffset(anchor, yLength); double x = hpos(anchor, start.getX(), end.getX()); return new Point3D(x + dx, start.getY() + dy, start.getZ()); } // anchor for y-marker label where line runs parallel to z-axis private Point3D calcAnchorYZ(Anchor2D anchor, Point3D start, Point3D end, double yLength) { double dx = hoffset(anchor, end.getZ() - start.getZ()); double dy = voffset(anchor, yLength); double z = hpos(anchor, start.getZ(), end.getZ()); return new Point3D(start.getX(), start.getY() + dy, z + dx); } // anchor for z-marker label where line runs parallel to x-axis private Point3D calcAnchorZX(Anchor2D anchor, Point3D start, Point3D end, double zLength) { double dx = hoffset(anchor, end.getX() - start.getX()); double dy = voffset(anchor, zLength); double x = hpos(anchor, start.getX(), end.getX()); return new Point3D(x + dx, start.getY(), start.getZ() + dy); } // anchor for z-marker label where line runs parallel to y-axis private Point3D calcAnchorZY(Anchor2D anchor, Point3D start, Point3D end, double zLength) { double dx = hoffset(anchor, end.getY() - start.getY()); double dy = voffset(anchor, zLength); double y = hpos(anchor, start.getY(), end.getY()); return new Point3D(start.getX(), y + dx, start.getZ() + dy); } // anchor for x-marker label where band runs parallel to y-axis private Point3D calcRangeAnchorXY(Anchor2D anchor, Point3D start1, Point3D end1, Point3D start2, Point3D end2) { Point2D p = anchor.resolveAnchorWithPercentOffset(start1.getY(), start1.getX(), end2.getY(), end2.getX()); return new Point3D(p.getY(), p.getX(), end1.getZ()); } // anchor for x-marker label where line runs parallel to z-axis private Point3D calcRangeAnchorXZ(Anchor2D anchor, Point3D start1, Point3D end1, Point3D start2, Point3D end2) { Point2D p = anchor.resolveAnchorWithPercentOffset(start1.getZ(), start1.getX(), end2.getZ(), end2.getX()); return new Point3D(p.getY(), end1.getY(), p.getX()); } // // anchor for y-marker label where line runs parallel to x-axis private Point3D calcRangeAnchorYX(Anchor2D anchor, Point3D start1, Point3D end1, Point3D start2, Point3D end2) { Point2D p = anchor.resolveAnchorWithPercentOffset(start1.getX(), start1.getY(), end2.getX(), end2.getY()); return new Point3D(p.getX(), p.getY(), end1.getZ()); } // // anchor for y-marker label where line runs parallel to z-axis private Point3D calcRangeAnchorYZ(Anchor2D anchor, Point3D start1, Point3D end1, Point3D start2, Point3D end2) { Point2D p = anchor.resolveAnchorWithPercentOffset(start1.getZ(), start1.getY(), end2.getZ(), end2.getY()); return new Point3D(start1.getX(), p.getY(), p.getX()); } // anchor for z-marker label where line runs parallel to x-axis private Point3D calcRangeAnchorZX(Anchor2D anchor, Point3D start1, Point3D end1, Point3D start2, Point3D end2) { Point2D p = anchor.resolveAnchorWithPercentOffset(start1.getX(), start1.getZ(), end2.getX(), end2.getZ()); return new Point3D(p.getX(), end1.getY(), p.getY()); } // anchor for z-marker label where line runs parallel to y-axis private Point3D calcRangeAnchorZY(Anchor2D anchor, Point3D start1, Point3D end1, Point3D start2, Point3D end2) { Point2D p = anchor.resolveAnchorWithPercentOffset(start1.getY(), start1.getZ(), end2.getY(), end2.getZ()); return new Point3D(end1.getX(), p.getX(), p.getY()); } /** * A special subclass of {@link Face} that is used by the {@link ChartBox3D} * so that when faces are sorted by z-order, the chart box sides are always * drawn first (furthest in the background). Also, these faces track * tick marks, values and anchor points. */ public static final class ChartBoxFace extends Face { /** Info about the x-axis ticks on edge A. */ private final List xTicksA; /** Info about the x-axis ticks on edge B. */ private final List xTicksB; /** Info about the y-axis ticks on edge A. */ private final List yTicksA; /** Info about the y-axis ticks on edge B. */ private final List yTicksB; /** Info about the z-axis ticks on edge A. */ private final List zTicksA; /** Info about the z-axis ticks on edge B. */ private final List zTicksB; private final List xMarkers; private final List yMarkers; private final List zMarkers; /** * Creates a new face for a {@link ChartBox3D}. * * @param owner the object that the new face belongs to ({@code null} * not permitted). * @param vertices the indices of the vertices. * * @since 1.3 */ public ChartBoxFace(Object3D owner, int[] vertices) { super(owner, vertices); this.xTicksA = new ArrayList<>(); this.xTicksB = new ArrayList<>(); this.yTicksA = new ArrayList<>(); this.yTicksB = new ArrayList<>(); this.zTicksA = new ArrayList<>(); this.zTicksB = new ArrayList<>(); this.xMarkers = new ArrayList<>(); this.yMarkers = new ArrayList<>(); this.zMarkers = new ArrayList<>(); } /** * Clears the ticks for the x-axis. */ public void clearXTicks() { this.xTicksA.clear(); this.xTicksB.clear(); } /** * Returns the x-axis tick data for edge A. * * @return The x-axis tick data for edge A. */ public List getXTicksA() { return this.xTicksA; } /** * Adds tick data for edges A and B. * * @param a data for a tick on edge A. * @param b data for a tick on edge B. */ public void addXTicks(TickData a, TickData b) { this.xTicksA.add(a); this.xTicksB.add(b); } /** * Returns the x-axis tick data for the edge B. * * @return The x-axis tick data for the edge B. */ public List getXTicksB() { return this.xTicksB; } /** * Adds tick data items for the y-axis. * * @param a data for a tick on edge A. * @param b data for a tick on edge B. */ public void addYTicks(TickData a, TickData b) { this.yTicksA.add(a); this.yTicksB.add(b); } /** * Returns the y-axis tick data for the edge A. * * @return The y-axis tick data for the edge A. */ public List getYTicksA() { return this.yTicksA; } /** * Returns the y-axis tick data for the edge B. * * @return The y-axis tick data for the edge B. */ public List getYTicksB() { return this.yTicksB; } /** * Adds tick data items for the z-axis. * * @param a data for a tick on edge A. * @param b data for a tick on edge B. */ public void addZTicks(TickData a, TickData b) { this.zTicksA.add(a); this.zTicksB.add(b); } /** * Returns the z-axis tick data for the edge A. * * @return The z-axis tick data for the edge A. */ public List getZTicksA() { return this.zTicksA; } /** * Returns the z-axis tick data for the edge B. * * @return The z-axis tick data for the edge B. */ public List getZTicksB() { return this.zTicksB; } /** * Adds marker data for the x-dimension. * * @param marker the marker data ({@code null} not permitted). */ public void addXMarker(MarkerData marker) { Args.nullNotPermitted(marker, "marker"); this.xMarkers.add(marker); } /** * Returns a list of marker data for the x-dimension (the list is not * modifiable). * * @return The markers (never {@code null}). */ public List getXMarkers() { return Collections.unmodifiableList(this.xMarkers); } /** * Adds marker data for the y-dimension. * * @param marker the marker data ({@code null} not permitted). */ public void addYMarker(MarkerData marker) { Args.nullNotPermitted(marker, "marker"); this.yMarkers.add(marker); } /** * Returns a list of marker data for the y-dimension (the list is not * modifiable). * * @return The markers (never {@code null}). */ public List getYMarkers() { return Collections.unmodifiableList(this.yMarkers); } /** * Adds marker data for the z-dimension. * * @param marker the marker data ({@code null} not permitted). */ public void addZMarker(MarkerData marker) { Args.nullNotPermitted(marker, "marker"); this.zMarkers.add(marker); } /** * Returns a list of marker data for the z-dimension (the list is not * modifiable). * * @return The markers (never {@code null}). */ public List getZMarkers() { return Collections.unmodifiableList(this.zMarkers); } /** * Returns {@code -123456f} which ensures that the chart box face * is always drawn first (before any data items). * * @param points the points (ignored here). * * @return {@code -123456f}. */ @Override public float calculateAverageZValue(Point3D[] points) { return -123456f; } } } orson-charts-2.1.0/src/main/java/org/jfree/chart3d/internal/ObjectUtils.java000066400000000000000000000126611417331271500267220ustar00rootroot00000000000000/* =========================================================== * Orson Charts : a 3D chart library for the Java(tm) platform * =========================================================== * * (C)opyright 2013-2022, by David Gilbert. All rights reserved. * * https://github.com/jfree/orson-charts * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . * * [Oracle and Java are registered trademarks of Oracle and/or its affiliates. * Other names may be trademarks of their respective owners.] * * If you do not wish to be bound by the terms of the GPL, an alternative * commercial license can be purchased. For details, please see visit the * Orson Charts home page: * * http://www.object-refinery.com/orsoncharts/index.html * */ package org.jfree.chart3d.internal; import java.awt.GradientPaint; import java.awt.LinearGradientPaint; import java.awt.Paint; import java.awt.RadialGradientPaint; import java.util.Arrays; /** * Some general utility methods for working with objects. */ public class ObjectUtils { /** * Returns {@code true} if the objects are equal or both {@code null}. * * @param obj1 object 1 ({@code null} permitted). * @param obj2 object 2 ({@code null} permitted). * * @return A boolean. */ public static boolean equals(Object obj1, Object obj2) { if (obj1 != null) { return obj1.equals(obj2); } else { return obj2 == null; } } /** * Returns the hash code of the object, or 0 if the object is * {@code null}. This method is provided in the Objects class in * Java 1.7, but you can use this one to run on Java 1.6. * * @param obj ({@code null} permitted). * * @return A hash code. * * @since 1.1 */ public static int hashCode(Object obj) { return obj != null ? obj.hashCode() : 0; } /** * Returns {@code true} if the two {@code Paint} objects are equal * OR both {@code null}. This method handles * {@code GradientPaint}, {@code LinearGradientPaint} and * {@code RadialGradientPaint} as a special cases, since those classes do * not override the {@code equals()} method. * * @param p1 paint 1 ({@code null} permitted). * @param p2 paint 2 ({@code null} permitted). * * @return A boolean. */ public static boolean equalsPaint(Paint p1, Paint p2) { if (p1 == p2) { return true; } // handle cases where either or both arguments are null if (p1 == null) { return (p2 == null); } if (p2 == null) { return false; } // handle GradientPaint as a special case... if (p1 instanceof GradientPaint && p2 instanceof GradientPaint) { GradientPaint gp1 = (GradientPaint) p1; GradientPaint gp2 = (GradientPaint) p2; return gp1.getColor1().equals(gp2.getColor1()) && gp1.getColor2().equals(gp2.getColor2()) && gp1.getPoint1().equals(gp2.getPoint1()) && gp1.getPoint2().equals(gp2.getPoint2()) && gp1.isCyclic() == gp2.isCyclic() && gp1.getTransparency() == gp1.getTransparency(); } else if (p1 instanceof LinearGradientPaint && p2 instanceof LinearGradientPaint) { LinearGradientPaint lgp1 = (LinearGradientPaint) p1; LinearGradientPaint lgp2 = (LinearGradientPaint) p2; return lgp1.getStartPoint().equals(lgp2.getStartPoint()) && lgp1.getEndPoint().equals(lgp2.getEndPoint()) && Arrays.equals(lgp1.getFractions(), lgp2.getFractions()) && Arrays.equals(lgp1.getColors(), lgp2.getColors()) && lgp1.getCycleMethod() == lgp2.getCycleMethod() && lgp1.getColorSpace() == lgp2.getColorSpace() && lgp1.getTransform().equals(lgp2.getTransform()); } else if (p1 instanceof RadialGradientPaint && p2 instanceof RadialGradientPaint) { RadialGradientPaint rgp1 = (RadialGradientPaint) p1; RadialGradientPaint rgp2 = (RadialGradientPaint) p2; return rgp1.getCenterPoint().equals(rgp2.getCenterPoint()) && rgp1.getRadius() == rgp2.getRadius() && rgp1.getFocusPoint().equals(rgp2.getFocusPoint()) && Arrays.equals(rgp1.getFractions(), rgp2.getFractions()) && Arrays.equals(rgp1.getColors(), rgp2.getColors()) && rgp1.getCycleMethod() == rgp2.getCycleMethod() && rgp1.getColorSpace() == rgp2.getColorSpace() && rgp1.getTransform().equals(rgp2.getTransform()); } else { return p1.equals(p2); } } } orson-charts-2.1.0/src/main/java/org/jfree/chart3d/internal/OnDrawHandler.java000066400000000000000000000135301417331271500271570ustar00rootroot00000000000000/* =========================================================== * Orson Charts : a 3D chart library for the Java(tm) platform * =========================================================== * * (C)opyright 2013-2022, by David Gilbert. All rights reserved. * * https://github.com/jfree/orson-charts * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . * * [Oracle and Java are registered trademarks of Oracle and/or its affiliates. * Other names may be trademarks of their respective owners.] * * If you do not wish to be bound by the terms of the GPL, an alternative * commercial license can be purchased. For details, please see visit the * Orson Charts home page: * * http://www.object-refinery.com/orsoncharts/index.html * */ package org.jfree.chart3d.internal; import java.awt.Graphics2D; import java.awt.geom.Rectangle2D; import java.util.HashMap; import java.util.Map; import org.jfree.chart3d.Chart3D; import org.jfree.chart3d.Chart3DHints; import org.jfree.chart3d.graphics3d.RenderedElement; import org.jfree.chart3d.graphics3d.RenderingInfo; import org.jfree.chart3d.interaction.InteractiveElementType; import static org.jfree.chart3d.interaction.InteractiveElementType.LEGEND_ITEM; import static org.jfree.chart3d.interaction.InteractiveElementType.SUBTITLE; import static org.jfree.chart3d.interaction.InteractiveElementType.TITLE; import org.jfree.chart3d.table.TableElement; import org.jfree.chart3d.table.TableElementOnDraw; /** * An 'onDraw' handler that handles two aspects related to chart interactivity: * (1) it adds a {@link RenderedElement} instance to the {@link RenderingInfo} * for each element in the chart that requires it, and (2) it adds element * hinting to the {@code Graphics2D} output (how this is handled by the * {@code Graphics2D} instance is implementation dependent). * * @since 1.3 */ public class OnDrawHandler implements TableElementOnDraw { /** The rendering info the be populated (if not null). */ private final RenderingInfo info; /** A flag indicating whether or not element hinting is added. */ boolean elementHinting; /** * Creates a new handler. * * @param info the rendering info to be populated ({@code null} * permitted). * @param elementHinting a flag that controls whether or not element * hinting is performed. */ public OnDrawHandler(RenderingInfo info, boolean elementHinting) { this.info = info; this.elementHinting = elementHinting; } @Override public void beforeDraw(TableElement element, Graphics2D g2, Rectangle2D bounds) { InteractiveElementType t = (InteractiveElementType) element.getProperty(TableElement.CLASS); // handle rendering info if (t != null && info != null) { switch (t) { case TITLE: case SUBTITLE: RenderedElement re = new RenderedElement(t, bounds); this.info.addElement(re); break; case LEGEND_ITEM: RenderedElement legendItemRE = new RenderedElement( InteractiveElementType.LEGEND_ITEM, bounds); legendItemRE.setProperty(Chart3D.SERIES_KEY, element.getProperty(Chart3D.SERIES_KEY)); this.info.addElement(legendItemRE); break; default: throw new RuntimeException(); } } // handle hinting if (t != null && this.elementHinting) { Map m = new HashMap<>(); switch (t) { case TITLE: m.put("ref", "{\"type\": \"title\"}"); g2.setRenderingHint(Chart3DHints.KEY_BEGIN_ELEMENT, m); break; case SUBTITLE: m.put("ref", "{\"type\": \"subtitle\"}"); g2.setRenderingHint(Chart3DHints.KEY_BEGIN_ELEMENT, m); break; case LEGEND_ITEM: m.put("ref", generateLegendItemRef(element)); g2.setRenderingHint(Chart3DHints.KEY_BEGIN_ELEMENT, m); break; default: throw new RuntimeException(); } } } @Override public void afterDraw(TableElement element, Graphics2D g2, Rectangle2D bounds) { if (!this.elementHinting) { return; } InteractiveElementType t = (InteractiveElementType) element.getProperty(TableElement.CLASS); if (t == null) { return; } switch (t) { case TITLE: case SUBTITLE: case LEGEND_ITEM: g2.setRenderingHint(Chart3DHints.KEY_END_ELEMENT, Boolean.TRUE); break; default: throw new RuntimeException("Seeing type " + t); } } private String generateLegendItemRef(TableElement element) { Object key = element.getProperty(Chart3D.SERIES_KEY); return "{\"type\": \"legendItem\", \"seriesKey\": \"" + key.toString() + "\"}"; } } orson-charts-2.1.0/src/main/java/org/jfree/chart3d/internal/SerialUtils.java000066400000000000000000000160161417331271500267310ustar00rootroot00000000000000/* =========================================================== * Orson Charts : a 3D chart library for the Java(tm) platform * =========================================================== * * (C)opyright 2013-2022, by David Gilbert. All rights reserved. * * https://github.com/jfree/orson-charts * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . * * [Oracle and Java are registered trademarks of Oracle and/or its affiliates. * Other names may be trademarks of their respective owners.] * * If you do not wish to be bound by the terms of the GPL, an alternative * commercial license can be purchased. For details, please see visit the * Orson Charts home page: * * http://www.object-refinery.com/orsoncharts/index.html * */ package org.jfree.chart3d.internal; import java.awt.BasicStroke; import java.awt.Color; import java.awt.GradientPaint; import java.awt.Paint; import java.awt.Stroke; import java.io.IOException; import java.io.ObjectInputStream; import java.io.ObjectOutputStream; import java.io.Serializable; /** * Serialization support methods. */ public class SerialUtils { private SerialUtils() { // no need to instantiate this class } /** * Reads a {@code Paint} object that has been serialized by the * {@link SerialUtils#writePaint(Paint, ObjectOutputStream)} method. * * @param stream the input stream ({@code null} not permitted). * * @return The paint object (possibly {@code null}). * * @throws IOException if there is an I/O problem. * @throws ClassNotFoundException if there is a problem loading a class. */ public static Paint readPaint(ObjectInputStream stream) throws IOException, ClassNotFoundException { Args.nullNotPermitted(stream, "stream"); Paint result = null; boolean isNull = stream.readBoolean(); if (!isNull) { Class c = (Class) stream.readObject(); if (Serializable.class.isAssignableFrom(c)) { result = (Paint) stream.readObject(); } else if (c.equals(GradientPaint.class)) { float x1 = stream.readFloat(); float y1 = stream.readFloat(); Color c1 = (Color) stream.readObject(); float x2 = stream.readFloat(); float y2 = stream.readFloat(); Color c2 = (Color) stream.readObject(); boolean isCyclic = stream.readBoolean(); result = new GradientPaint(x1, y1, c1, x2, y2, c2, isCyclic); } } return result; } /** * Serializes a {@code Paint} object. * * @param paint the paint object ({@code null} permitted). * @param stream the output stream ({@code null} not permitted). * * @throws IOException if there is an I/O error. */ public static void writePaint(Paint paint, ObjectOutputStream stream) throws IOException { Args.nullNotPermitted(stream, "stream"); if (paint != null) { stream.writeBoolean(false); stream.writeObject(paint.getClass()); if (paint instanceof Serializable) { stream.writeObject(paint); } else if (paint instanceof GradientPaint) { GradientPaint gp = (GradientPaint) paint; stream.writeFloat((float) gp.getPoint1().getX()); stream.writeFloat((float) gp.getPoint1().getY()); stream.writeObject(gp.getColor1()); stream.writeFloat((float) gp.getPoint2().getX()); stream.writeFloat((float) gp.getPoint2().getY()); stream.writeObject(gp.getColor2()); stream.writeBoolean(gp.isCyclic()); } } else { stream.writeBoolean(true); } } /** * Reads a {@code Stroke} object that has been serialized by the * {@link SerialUtils#writeStroke(Stroke, ObjectOutputStream)} method. * * @param stream the input stream ({@code null} not permitted). * * @return The stroke object (possibly {@code null}). * * @throws IOException if there is an I/O problem. * @throws ClassNotFoundException if there is a problem loading a class. */ public static Stroke readStroke(ObjectInputStream stream) throws IOException, ClassNotFoundException { Args.nullNotPermitted(stream, "stream"); Stroke result = null; boolean isNull = stream.readBoolean(); if (!isNull) { Class c = (Class) stream.readObject(); if (c.equals(BasicStroke.class)) { float width = stream.readFloat(); int cap = stream.readInt(); int join = stream.readInt(); float miterLimit = stream.readFloat(); float[] dash = (float[]) stream.readObject(); float dashPhase = stream.readFloat(); result = new BasicStroke(width, cap, join, miterLimit, dash, dashPhase); } else { result = (Stroke) stream.readObject(); } } return result; } /** * Serializes a {@code Stroke} object. This code handles the * {@code BasicStroke} class which is the only {@code Stroke} * implementation provided by the JDK (and isn't directly * {@code Serializable}). * * @param stroke the stroke object ({@code null} permitted). * @param stream the output stream ({@code null} not permitted). * * @throws IOException if there is an I/O error. */ public static void writeStroke(Stroke stroke, ObjectOutputStream stream) throws IOException { Args.nullNotPermitted(stream, "stream"); if (stroke != null) { stream.writeBoolean(false); if (stroke instanceof BasicStroke) { BasicStroke s = (BasicStroke) stroke; stream.writeObject(BasicStroke.class); stream.writeFloat(s.getLineWidth()); stream.writeInt(s.getEndCap()); stream.writeInt(s.getLineJoin()); stream.writeFloat(s.getMiterLimit()); stream.writeObject(s.getDashArray()); stream.writeFloat(s.getDashPhase()); } else { stream.writeObject(stroke.getClass()); stream.writeObject(stroke); } } else { stream.writeBoolean(true); } } } orson-charts-2.1.0/src/main/java/org/jfree/chart3d/internal/TextUtils.java000066400000000000000000000554141417331271500264430ustar00rootroot00000000000000/* =========================================================== * Orson Charts : a 3D chart library for the Java(tm) platform * =========================================================== * * (C)opyright 2013-2022, by David Gilbert. All rights reserved. * * https://github.com/jfree/orson-charts * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . * * [Oracle and Java are registered trademarks of Oracle and/or its affiliates. * Other names may be trademarks of their respective owners.] * * If you do not wish to be bound by the terms of the GPL, an alternative * commercial license can be purchased. For details, please see visit the * Orson Charts home page: * * http://www.object-refinery.com/orsoncharts/index.html * */ package org.jfree.chart3d.internal; import java.awt.Font; import java.awt.FontMetrics; import java.awt.Graphics2D; import java.awt.Shape; import java.awt.font.FontRenderContext; import java.awt.font.LineMetrics; import java.awt.font.TextLayout; import java.awt.geom.AffineTransform; import java.awt.geom.Rectangle2D; import java.text.AttributedString; import org.jfree.chart3d.graphics2d.TextAnchor; /** * Utility methods for working with text. */ public class TextUtils { private TextUtils() { // no need to instantiate this } /** * Draws a string such that the specified anchor point is aligned to the * given {@code (x, y)} location, and returns a bounding rectangle * for the text. * * @param text the text. * @param g2 the graphics device ({@code null} not permitted). * @param x the x coordinate (Java 2D). * @param y the y coordinate (Java 2D). * @param anchor the anchor location ({@code null} not permitted). * * @return The text bounds (adjusted for the text position). */ public static Rectangle2D drawAlignedString(String text, Graphics2D g2, float x, float y, TextAnchor anchor) { Rectangle2D textBounds = new Rectangle2D.Double(); float[] adjust = deriveTextBoundsAnchorOffsets(g2, text, anchor, textBounds); // adjust text bounds to match string position textBounds.setRect(x + adjust[0], y + adjust[1] + adjust[2], textBounds.getWidth(), textBounds.getHeight()); g2.drawString(text, x + adjust[0], y + adjust[1]); return textBounds; } /** * Returns the bounds of an aligned string. * * @param text the string ({@code null} not permitted). * @param g2 the graphics target ({@code null} not permitted). * @param x the x-coordinate. * @param y the y-coordinate. * @param anchor the anchor point on the text that will be aligned to * {@code (x, y)} ({@code null} not permitted). * * @return The text bounds (never {@code null}). * * @since 1.3 */ public static Rectangle2D calcAlignedStringBounds(String text, Graphics2D g2, float x, float y, TextAnchor anchor) { Rectangle2D textBounds = new Rectangle2D.Double(); float[] adjust = deriveTextBoundsAnchorOffsets(g2, text, anchor, textBounds); // adjust text bounds to match string position textBounds.setRect(x + adjust[0], y + adjust[1] + adjust[2], textBounds.getWidth(), textBounds.getHeight()); return textBounds; } /** * A utility method that calculates the anchor offsets for a string. * Normally, the {@code (x, y)} coordinate for drawing text is a point on * the baseline at the left of the text string. If you add these offsets * to {@code (x, y)} and draw the string, then the anchor point should * coincide with the {@code (x, y)} point. * * @param g2 the graphics device (not {@code null}). * @param text the text. * @param anchor the anchor point ({@code null} not permitted). * * @return The offsets. */ private static float[] deriveTextBoundsAnchorOffsets(Graphics2D g2, String text, TextAnchor anchor) { float[] result = new float[2]; FontRenderContext frc = g2.getFontRenderContext(); Font f = g2.getFont(); FontMetrics fm = g2.getFontMetrics(f); Rectangle2D bounds = getTextBounds(text, fm); LineMetrics metrics = f.getLineMetrics(text, frc); float ascent = metrics.getAscent(); float halfAscent = ascent / 2.0f; float descent = metrics.getDescent(); float leading = metrics.getLeading(); float xAdj = 0.0f; float yAdj = 0.0f; if (anchor.isHorizontalCenter()) { xAdj = (float) -bounds.getWidth() / 2.0f; } else if (anchor.isRight()) { xAdj = (float) -bounds.getWidth(); } if (anchor.isTop()) { yAdj = -descent - leading + (float) bounds.getHeight(); } else if (anchor.isHalfAscent()) { yAdj = halfAscent; } else if (anchor.isHalfHeight()) { yAdj = -descent - leading + (float) (bounds.getHeight() / 2.0); } else if (anchor.isBaseline()) { yAdj = 0.0f; } else if (anchor.isBottom()) { yAdj = -metrics.getDescent() - metrics.getLeading(); } result[0] = xAdj; result[1] = yAdj; return result; } /** * A utility method that calculates the anchor offsets for a string. * Normally, the {@code (x, y)} coordinate for drawing text is a point on * the baseline at the left of the text string. If you add these offsets * to {@code (x, y)} and draw the string, then the anchor point should * coincide with the {@code (x, y)} point. * * @param g2 the graphics device (not {@code null}). * @param text the text. * @param anchor the anchor point ({@code null} not permitted). * @param textBounds the text bounds (if not {@code null}, this * object will be updated by this method to match the * string bounds). * * @return The offsets. */ private static float[] deriveTextBoundsAnchorOffsets(Graphics2D g2, String text, TextAnchor anchor, Rectangle2D textBounds) { float[] result = new float[3]; FontRenderContext frc = g2.getFontRenderContext(); Font f = g2.getFont(); FontMetrics fm = g2.getFontMetrics(f); Rectangle2D bounds = getTextBounds(text, fm); LineMetrics metrics = f.getLineMetrics(text, frc); float ascent = metrics.getAscent(); result[2] = -ascent; float halfAscent = ascent / 2.0f; float descent = metrics.getDescent(); float leading = metrics.getLeading(); float xAdj = 0.0f; float yAdj = 0.0f; if (anchor.isHorizontalCenter()) { xAdj = (float) -bounds.getWidth() / 2.0f; } else if (anchor.isRight()) { xAdj = (float) -bounds.getWidth(); } if (anchor.isTop()) { yAdj = -descent - leading + (float) bounds.getHeight(); } else if (anchor.isHalfAscent()) { yAdj = halfAscent; } else if (anchor.isHorizontalCenter()) { yAdj = -descent - leading + (float) (bounds.getHeight() / 2.0); } else if (anchor.isBaseline()) { yAdj = 0.0f; } else if (anchor.isBottom()) { yAdj = -metrics.getDescent() - metrics.getLeading(); } if (textBounds != null) { textBounds.setRect(bounds); } result[0] = xAdj; result[1] = yAdj; return result; } /** * Returns the bounds for the specified text. The supplied text is * assumed to be on a single line (no carriage return or newline * characters). * * @param text the text ({@code null} not permitted). * @param fm the font metrics ({@code null} not permitted). * * @return The text bounds. */ public static Rectangle2D getTextBounds(String text, FontMetrics fm) { return getTextBounds(text, 0.0, 0.0, fm); } /** * Returns the bounds for the specified text when it is drawn with the * left-baseline aligned to the point {@code (x, y)}. * * @param text the text ({@code null} not permitted). * @param x the x-coordinate. * @param y the y-coordinate. * @param fm the font metrics ({@code null} not permitted). * * @return The bounding rectangle (never {@code null}). */ public static Rectangle2D getTextBounds(String text, double x, double y, FontMetrics fm) { Args.nullNotPermitted(text, "text"); Args.nullNotPermitted(fm, "fm"); double width = fm.stringWidth(text); double height = fm.getHeight(); return new Rectangle2D.Double(x, y - fm.getAscent(), width, height); } /** * Draws a string that is aligned by one anchor point and rotated about * another anchor point. * * @param text the text ({@code null} not permitted). * @param g2 the graphics target ({@code null} not permitted). * @param x the x-coordinate for positioning the text. * @param y the y-coordinate for positioning the text. * @param textAnchor the text anchor ({@code null} not permitted). * @param angle the rotation angle. * @param rotationX the x-coordinate for the rotation anchor point. * @param rotationY the y-coordinate for the rotation anchor point. * * @return The text bounds (never {@code null}). */ public static Shape drawRotatedString(String text, Graphics2D g2, float x, float y, TextAnchor textAnchor, double angle, float rotationX, float rotationY) { Args.nullNotPermitted(text, "text"); float[] textAdj = deriveTextBoundsAnchorOffsets(g2, text, textAnchor); return drawRotatedString(text, g2, x + textAdj[0], y + textAdj[1], angle, rotationX, rotationY); } /** * Draws a string that is aligned by one anchor point and rotated about * another anchor point, and returns a bounding shape for the text. * * @param text the text ({@code null} not permitted). * @param g2 the graphics device ({@code null} not permitted). * @param x the x-coordinate for positioning the text. * @param y the y-coordinate for positioning the text. * @param textAnchor the text anchor ({@code null} not permitted). * @param angle the rotation angle (in radians). * @param rotationAnchor the rotation anchor ({@code null} not permitted). * * @return A bounding shape for the text. */ public static Shape drawRotatedString(String text, Graphics2D g2, float x, float y, TextAnchor textAnchor, double angle, TextAnchor rotationAnchor) { Args.nullNotPermitted(text, "text"); float[] textAdj = deriveTextBoundsAnchorOffsets(g2, text, textAnchor); float[] rotateAdj = deriveRotationAnchorOffsets(g2, text, rotationAnchor); return drawRotatedString(text, g2, x + textAdj[0], y + textAdj[1], angle, x + textAdj[0] + rotateAdj[0], y + textAdj[1] + rotateAdj[1]); } /** * A utility method that calculates the rotation anchor offsets for a * string. These offsets are relative to the text starting coordinate * ({@code BASELINE_LEFT}). * * @param g2 the graphics device ({@code null} not permitted). * @param text the text ({@code null} not permitted). * @param anchor the anchor point ({@code null} not permitted). * * @return The offsets. */ private static float[] deriveRotationAnchorOffsets(Graphics2D g2, String text, TextAnchor anchor) { float[] result = new float[2]; FontRenderContext frc = g2.getFontRenderContext(); LineMetrics metrics = g2.getFont().getLineMetrics(text, frc); FontMetrics fm = g2.getFontMetrics(); Rectangle2D bounds = TextUtils.getTextBounds(text, fm); float ascent = metrics.getAscent(); float halfAscent = ascent / 2.0f; float descent = metrics.getDescent(); float leading = metrics.getLeading(); float xAdj = 0.0f; float yAdj = 0.0f; if (anchor.isLeft()) { xAdj = 0.0f; } else if (anchor.isHorizontalCenter()) { xAdj = (float) bounds.getWidth() / 2.0f; } else if (anchor.isRight()) { xAdj = (float) bounds.getWidth(); } if (anchor.isTop()) { yAdj = descent + leading - (float) bounds.getHeight(); } else if (anchor.isHalfHeight()) { yAdj = descent + leading - (float) (bounds.getHeight() / 2.0); } else if (anchor.isHalfAscent()) { yAdj = -halfAscent; } else if (anchor.isBaseline()) { yAdj = 0.0f; } else if (anchor.isBottom()) { yAdj = metrics.getDescent() + metrics.getLeading(); } result[0] = xAdj; result[1] = yAdj; return result; } /** * A utility method for drawing rotated text. *

* A common rotation is {@code -Math.PI/2} which draws text 'vertically' * (with the top of the characters on the left). * * @param text the text ({@code null} not permitted) * @param g2 the graphics target ({@code null} not permitted). * @param angle the angle of the (clockwise) rotation (in radians). * @param x the x-coordinate. * @param y the y-coordinate. * * @return The text bounds. */ public static Shape drawRotatedString(String text, Graphics2D g2, double angle, float x, float y) { return drawRotatedString(text, g2, x, y, angle, x, y); } /** * A utility method for drawing rotated text. *

* A common rotation is {@code -Math.PI/2} which draws text 'vertically' * (with the top of the characters on the left). * * @param text the text ({@code null} not permitted). * @param g2 the graphics device ({@code null} not permitted). * @param textX the x-coordinate for the text (before rotation). * @param textY the y-coordinate for the text (before rotation). * @param angle the angle of the (clockwise) rotation (in radians). * @param rotateX the point about which the text is rotated. * @param rotateY the point about which the text is rotated. * * @return The bounds for the rotated text (never {@code null}). */ public static Shape drawRotatedString(String text, Graphics2D g2, float textX, float textY, double angle, float rotateX, float rotateY) { Args.nullNotPermitted(text, "text"); AffineTransform saved = g2.getTransform(); Rectangle2D rect = TextUtils.getTextBounds(text, textX, textY, g2.getFontMetrics()); AffineTransform rotate = AffineTransform.getRotateInstance( angle, rotateX, rotateY); Shape bounds = rotate.createTransformedShape(rect); g2.transform(rotate); g2.drawString(text, textX, textY); g2.setTransform(saved); return bounds; } /** * Draws the attributed string at {@code (x, y)}, rotated by the * specified angle about {@code (x, y)}. * * @param text the attributed string ({@code null} not permitted). * @param g2 the graphics output target ({@code null} not permitted). * @param angle the angle. * @param x the x-coordinate. * @param y the y-coordinate. * * @return The text bounds (never {@code null}). * * @since 1.2 */ public static Shape drawRotatedString(AttributedString text, Graphics2D g2, double angle, float x, float y) { return drawRotatedString(text, g2, x, y, angle, x, y); } /** * Draws the attributed string at {@code (textX, textY)}, rotated by * the specified angle about {@code (rotateX, rotateY)}. * * @param text the attributed string ({@code null} not permitted). * @param g2 the graphics output target ({@code null} not permitted). * @param textX the x-coordinate for the text alignment point. * @param textY the y-coordinate for the text alignment point. * @param angle the rotation angle (in radians). * @param rotateX the x-coordinate for the rotation point. * @param rotateY the y-coordinate for the rotation point. * * @return The text bounds (never {@code null}). * * @since 1.2 */ public static Shape drawRotatedString(AttributedString text, Graphics2D g2, float textX, float textY, double angle, float rotateX, float rotateY) { Args.nullNotPermitted(text, "text"); AffineTransform saved = g2.getTransform(); AffineTransform rotate = AffineTransform.getRotateInstance(angle, rotateX, rotateY); g2.transform(rotate); TextLayout tl = new TextLayout(text.getIterator(), g2.getFontRenderContext()); Rectangle2D rect = tl.getBounds(); tl.draw(g2, textX, textY); g2.setTransform(saved); return rotate.createTransformedShape(rect); } /** * Draws the attributed string aligned to the point {@code (x, y)}, * rotated by the specified angle about {@code rotationAnchor}. * * @param text the attributed string ({@code null} not permitted). * @param g2 the graphics target ({@code null} not permitted). * @param x the x-coordinate. * @param y the y-coordinate. * @param textAnchor the text anchor ({@code null} not permitted). * @param angle the rotation angle (in radians). * @param rotationAnchor the rotation anchor ({@code null} not * permitted). * @param nonRotatedBounds if not {@code null} this rectangle will * be updated with the non-rotated bounds of the text for the caller * to use. * * @return The text bounds (never {@code null}). * * @since 1.2 */ public static Shape drawRotatedString(AttributedString text, Graphics2D g2, float x, float y, TextAnchor textAnchor, double angle, TextAnchor rotationAnchor, Rectangle2D nonRotatedBounds) { Args.nullNotPermitted(text, "text"); float[] textAdj = deriveTextBoundsAnchorOffsets(g2, text, textAnchor, nonRotatedBounds); float[] rotateAdj = deriveRotationAnchorOffsets(g2, text, rotationAnchor); return drawRotatedString(text, g2, x + textAdj[0], y + textAdj[1], angle, x + textAdj[0] + rotateAdj[0], y + textAdj[1] + rotateAdj[1]); } /** * Calculates the x and y offsets required to align the text with the * specified {@code anchor}. * * @param g2 the graphics target ({@code null} not permitted). * @param text the text ({@code null} not permitted). * @param anchor the anchor ({@code null} not permitted). * @param textBounds if not {@code null}, this rectangle will be * updated with the bounds of the text (for the caller to use). * * @return An array of two floats dx and dy. */ private static float[] deriveTextBoundsAnchorOffsets(Graphics2D g2, AttributedString text, TextAnchor anchor, Rectangle2D textBounds) { TextLayout layout = new TextLayout(text.getIterator(), g2.getFontRenderContext()); Rectangle2D bounds = layout.getBounds(); float[] result = new float[3]; float ascent = layout.getAscent(); result[2] = -ascent; float halfAscent = ascent / 2.0f; float descent = layout.getDescent(); float leading = layout.getLeading(); float xAdj = 0.0f; float yAdj = 0.0f; if (anchor.isHorizontalCenter()) { xAdj = (float) -bounds.getWidth() / 2.0f; } else if (anchor.isRight()) { xAdj = (float) -bounds.getWidth(); } if (anchor.isTop()) { yAdj = -descent - leading + (float) bounds.getHeight(); } else if (anchor.isHalfAscent()) { yAdj = halfAscent; } else if (anchor.isHalfHeight()) { yAdj = -descent - leading + (float) (bounds.getHeight() / 2.0); } else if (anchor.isBaseline()) { yAdj = 0.0f; } else if (anchor.isBottom()) { yAdj = -descent - leading; } if (textBounds != null) { textBounds.setRect(bounds); } result[0] = xAdj; result[1] = yAdj; return result; } /** * A utility method that calculates the rotation anchor offsets for a * string. These offsets are relative to the text starting coordinate * ({@code BASELINE_LEFT}). * * @param g2 the graphics device ({@code null} not permitted). * @param text the text ({@code null} not permitted). * @param anchor the anchor point ({@code null} not permitted). * * @return The offsets. */ private static float[] deriveRotationAnchorOffsets(Graphics2D g2, AttributedString text, TextAnchor anchor) { float[] result = new float[2]; TextLayout layout = new TextLayout(text.getIterator(), g2.getFontRenderContext()); Rectangle2D bounds = layout.getBounds(); float ascent = layout.getAscent(); float halfAscent = ascent / 2.0f; float descent = layout.getDescent(); float leading = layout.getLeading(); float xAdj = 0.0f; float yAdj = 0.0f; if (anchor.isLeft()) { xAdj = 0.0f; } else if (anchor.isHorizontalCenter()) { xAdj = (float) bounds.getWidth() / 2.0f; } else if (anchor.isRight()) { xAdj = (float) bounds.getWidth(); } if (anchor.isTop()) { yAdj = descent + leading - (float) bounds.getHeight(); } else if (anchor.isHalfHeight()) { yAdj = descent + leading - (float) (bounds.getHeight() / 2.0); } else if (anchor.isHalfAscent()) { yAdj = -halfAscent; } else if (anchor.isBaseline()) { yAdj = 0.0f; } else if (anchor.isBottom()) { yAdj = descent + leading; } result[0] = xAdj; result[1] = yAdj; return result; } } orson-charts-2.1.0/src/main/java/org/jfree/chart3d/label/000077500000000000000000000000001417331271500230655ustar00rootroot00000000000000orson-charts-2.1.0/src/main/java/org/jfree/chart3d/label/CategoryItemLabelGenerator.java000066400000000000000000000046731417331271500311450ustar00rootroot00000000000000/* =========================================================== * Orson Charts : a 3D chart library for the Java(tm) platform * =========================================================== * * (C)opyright 2013-2022, by David Gilbert. All rights reserved. * * https://github.com/jfree/orson-charts * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . * * [Oracle and Java are registered trademarks of Oracle and/or its affiliates. * Other names may be trademarks of their respective owners.] * * If you do not wish to be bound by the terms of the GPL, an alternative * commercial license can be purchased. For details, please see visit the * Orson Charts home page: * * http://www.object-refinery.com/orsoncharts/index.html * */ package org.jfree.chart3d.label; import org.jfree.chart3d.data.category.CategoryDataset3D; /** * An item label generator for category charts (this is used for tooltips and * data item labels). Note that this generator is used for individual data * items, and is distinct from the {@link CategoryLabelGenerator} which * generates labels for series keys, column keys and row keys. * The {@link StandardCategoryItemLabelGenerator} class provides the default * implementation. * * @since 1.3 */ public interface CategoryItemLabelGenerator { /** * Generates a label for one series in a {@link CategoryDataset3D}. * * @param dataset the dataset ({@code null} not permitted). * @param seriesKey the series key ({@code null} not permitted). * @param rowKey the row key ({@code null} not permitted). * @param columnKey the column key ({@code null} not permitted). * * @return The series label (possibly {@code null}). */ String generateItemLabel(CategoryDataset3D dataset, Comparable seriesKey, Comparable rowKey, Comparable columnKey); }orson-charts-2.1.0/src/main/java/org/jfree/chart3d/label/CategoryLabelGenerator.java000066400000000000000000000063721417331271500303240ustar00rootroot00000000000000/* =========================================================== * Orson Charts : a 3D chart library for the Java(tm) platform * =========================================================== * * (C)opyright 2013-2022, by David Gilbert. All rights reserved. * * https://github.com/jfree/orson-charts * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . * * [Oracle and Java are registered trademarks of Oracle and/or its affiliates. * Other names may be trademarks of their respective owners.] * * If you do not wish to be bound by the terms of the GPL, an alternative * commercial license can be purchased. For details, please see visit the * Orson Charts home page: * * http://www.object-refinery.com/orsoncharts/index.html * */ package org.jfree.chart3d.label; import org.jfree.chart3d.data.category.CategoryDataset3D; import org.jfree.chart3d.plot.CategoryPlot3D; /** * A label generator for category charts, used to create labels for the axes * and for the chart legend. The ({@link StandardCategoryLabelGenerator}) class * provides the default implementation. *

* Note that a different generator is used for item labels in * a {@link CategoryPlot3D} - see the {@link CategoryItemLabelGenerator} * interface. * * @param The series key type (must implement Comparable). * @param The row key type (must implement Comparable). * @param The column key type (must implement Comparable). * * @since 1.2 */ public interface CategoryLabelGenerator, R extends Comparable, C extends Comparable> { /** * Generates a label for one series in a {@link CategoryDataset3D}. * * @param dataset the dataset ({@code null} not permitted). * @param seriesKey the series key ({@code null} not permitted). * * @return The series label (possibly {@code null}). */ String generateSeriesLabel(CategoryDataset3D dataset, S seriesKey); /** * Generates a label for one row in a {@link CategoryDataset3D}. * * @param dataset the dataset ({@code null} not permitted). * @param rowKey the key ({@code null} not permitted). * * @return The row label (possibly {@code null}). */ String generateRowLabel(CategoryDataset3D dataset, R rowKey); /** * Generates a label for one column in a {@link CategoryDataset3D}. * * @param dataset the dataset ({@code null} not permitted). * @param columnKey the key ({@code null} not permitted). * * @return The column label (possibly {@code null}). */ String generateColumnLabel(CategoryDataset3D dataset, C columnKey); }orson-charts-2.1.0/src/main/java/org/jfree/chart3d/label/ItemLabelPositioning.java000066400000000000000000000033171417331271500300150ustar00rootroot00000000000000/* =========================================================== * Orson Charts : a 3D chart library for the Java(tm) platform * =========================================================== * * (C)opyright 2013-2022, by David Gilbert. All rights reserved. * * https://github.com/jfree/orson-charts * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . * * [Oracle and Java are registered trademarks of Oracle and/or its affiliates. * Other names may be trademarks of their respective owners.] * * If you do not wish to be bound by the terms of the GPL, an alternative * commercial license can be purchased. For details, please see visit the * Orson Charts home page: * * http://www.object-refinery.com/orsoncharts/index.html * */ package org.jfree.chart3d.label; /** * An enumeration of the item label positioning types. * * @since 1.3 */ public enum ItemLabelPositioning { /** * Labels are placed at the front and the back (typically only one of the * two is visible at any time). */ FRONT_AND_BACK, /** * A single label is placed centrally. */ CENTRAL } orson-charts-2.1.0/src/main/java/org/jfree/chart3d/label/PieLabelGenerator.java000066400000000000000000000036041417331271500272570ustar00rootroot00000000000000/* =========================================================== * Orson Charts : a 3D chart library for the Java(tm) platform * =========================================================== * * (C)opyright 2013-2022, by David Gilbert. All rights reserved. * * https://github.com/jfree/orson-charts * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . * * [Oracle and Java are registered trademarks of Oracle and/or its affiliates. * Other names may be trademarks of their respective owners.] * * If you do not wish to be bound by the terms of the GPL, an alternative * commercial license can be purchased. For details, please see visit the * Orson Charts home page: * * http://www.object-refinery.com/orsoncharts/index.html * */ package org.jfree.chart3d.label; import org.jfree.chart3d.data.PieDataset3D; /** * A label generator for pie charts. A default implementation * ({@link StandardPieLabelGenerator}) is provided. */ public interface PieLabelGenerator { /** * Returns a label for one data item in a pie chart. * * @param dataset the dataset ({@code null} not permitted). * @param key the key ({@code null} not permitted). * * @return The label (possibly {@code null}). */ String generateLabel(PieDataset3D dataset, Comparable key); }orson-charts-2.1.0/src/main/java/org/jfree/chart3d/label/StandardCategoryItemLabelGenerator.java000066400000000000000000000167211417331271500326230ustar00rootroot00000000000000/* =========================================================== * Orson Charts : a 3D chart library for the Java(tm) platform * =========================================================== * * (C)opyright 2013-2022, by David Gilbert. All rights reserved. * * https://github.com/jfree/orson-charts * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . * * [Oracle and Java are registered trademarks of Oracle and/or its affiliates. * Other names may be trademarks of their respective owners.] * * If you do not wish to be bound by the terms of the GPL, an alternative * commercial license can be purchased. For details, please see visit the * Orson Charts home page: * * http://www.object-refinery.com/orsoncharts/index.html * */ package org.jfree.chart3d.label; import java.io.Serializable; import java.util.Formatter; import org.jfree.chart3d.data.KeyedValues3DItemKey; import org.jfree.chart3d.data.category.CategoryDataset3D; import org.jfree.chart3d.interaction.KeyedValues3DItemSelection; import org.jfree.chart3d.interaction.StandardKeyedValues3DItemSelection; import org.jfree.chart3d.internal.Args; import org.jfree.chart3d.internal.ObjectUtils; /** * A default implementation of the {@link CategoryItemLabelGenerator} interface. * The implementation uses a {@link java.util.Formatter} instance to generate * the labels. Four values are passed to the formatter: (1) the key for * the series, (2) the row key, (3) the column key and (4) the data value. *

* NOTE: This class is serializable, but the serialization format is subject * to change in future releases and should not be relied upon for persisting * instances of this class. * * @since 1.3 */ @SuppressWarnings("serial") public class StandardCategoryItemLabelGenerator implements CategoryItemLabelGenerator, Serializable { /** * A template string that will show just the value (to 2 decimal places). * * @since 1.3 */ public static final String VALUE_TEMPLATE = "%4$.2f"; /** * A template string that will show the series, row and column keys plus * the data value. * * @since 1.3 */ public static final String KEYS_AND_VALUE_TEMPLATE = "%s, %s, %s = %4$.3f"; /** * A template that shows the series key, column key and value (the row * key is omitted because it is often the same as the series key). * * @since 1.3 */ public static final String SERIES_AND_COLUMN_KEYS_AND_VALUE_TEMPLATE = "%1$s, %3$s = %4$.3f"; /** * The default template string (used in the default constructor, it is * equivalent to {@link #SERIES_AND_COLUMN_KEYS_AND_VALUE_TEMPLATE}). * * @since 1.3 */ public static final String DEFAULT_TEMPLATE = SERIES_AND_COLUMN_KEYS_AND_VALUE_TEMPLATE; /** The template. */ private String template; /** * If this object is not-{@code null}, an item label will only be * returned by this generator if the selection contains the item that * the label is to be generated for. */ private KeyedValues3DItemSelection itemSelection; /** * The default constructor. */ public StandardCategoryItemLabelGenerator() { this(DEFAULT_TEMPLATE); } /** * Creates a new instance with the specified template string (which will * be passed to a {@code java.util.Formatter} instance when generating * labels). See the class description for an explanation of the values * that are available for use in the template string. * * @param template the template ({@code null} not permitted). */ public StandardCategoryItemLabelGenerator(String template) { Args.nullNotPermitted(template, "template"); this.template = template; this.itemSelection = null; } /** * Returns the item selection. The default value is {@code null}. * * @return The item selection. * * @since 1.3 */ public KeyedValues3DItemSelection getItemSelection() { return this.itemSelection; } /** * Sets the item selection (labels will be created by this generator only * for data items that are contained in the collection). If you set the * selection to {@code null} then the generator will create labels for * all data items. * * @param selection the selection ({@code null} permitted). */ public void setItemSelection(StandardKeyedValues3DItemSelection selection) { this.itemSelection = selection; } /** * Generates the item label for one data item in a category chart. * * @param dataset the dataset ({@code null} not permitted). * @param seriesKey the series key ({@code null} not permitted). * @param rowKey the row key ({@code null} not permitted). * @param columnKey the column key ({@code null} not permitted). * * @return The label (never {@code null} for this implementation). */ @Override @SuppressWarnings("unchecked") public String generateItemLabel(CategoryDataset3D dataset, Comparable seriesKey, Comparable rowKey, Comparable columnKey) { Args.nullNotPermitted(dataset, "dataset"); Args.nullNotPermitted(seriesKey, "seriesKey"); Args.nullNotPermitted(rowKey, "rowKey"); Args.nullNotPermitted(columnKey, "columnKey"); if (this.itemSelection != null) { KeyedValues3DItemKey key = new KeyedValues3DItemKey(seriesKey, rowKey, columnKey); if (!this.itemSelection.isSelected(key)) { return null; } } Formatter formatter = new Formatter(new StringBuilder()); Number value = (Number) dataset.getValue(seriesKey, rowKey, columnKey); Double d = null; if (value != null) { d = value.doubleValue(); } formatter.format(this.template, seriesKey, rowKey, columnKey, d); String result = formatter.toString(); formatter.close(); return result; } /** * Tests this label generator for equality with an arbitrary object. * * @param obj the object ({@code null} permitted). * * @return A boolean. */ @Override public boolean equals(Object obj) { if (obj == this) { return true; } if (!(obj instanceof StandardCategoryItemLabelGenerator)) { return false; } StandardCategoryItemLabelGenerator that = (StandardCategoryItemLabelGenerator) obj; if (!this.template.equals(that.template)) { return false; } if (!ObjectUtils.equals(this.itemSelection, that.itemSelection)) { return false; } return true; } @Override public int hashCode() { return this.template.hashCode(); } } orson-charts-2.1.0/src/main/java/org/jfree/chart3d/label/StandardCategoryLabelGenerator.java000066400000000000000000000164001417331271500317760ustar00rootroot00000000000000/* =========================================================== * Orson Charts : a 3D chart library for the Java(tm) platform * =========================================================== * * (C)opyright 2013-2022, by David Gilbert. All rights reserved. * * https://github.com/jfree/orson-charts * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . * * [Oracle and Java are registered trademarks of Oracle and/or its affiliates. * Other names may be trademarks of their respective owners.] * * If you do not wish to be bound by the terms of the GPL, an alternative * commercial license can be purchased. For details, please see visit the * Orson Charts home page: * * http://www.object-refinery.com/orsoncharts/index.html * */ package org.jfree.chart3d.label; import java.io.Serializable; import java.util.Formatter; import org.jfree.chart3d.data.DataUtils; import org.jfree.chart3d.data.category.CategoryDataset3D; import org.jfree.chart3d.internal.Args; /** * A default implementation of the {@link CategoryLabelGenerator} interface. * The implementation uses a {@link java.util.Formatter} instance to generate * the labels. Three values are passed to the formatter: (1) the key for * the series, row or column, (2) the count for the number of * non-{@code null} items in the series, row or column (as an * {@code Integer}) and (3) the total of the non-{@code null} values * (as a {@code Double}). *

* NOTE: This class is serializable, but the serialization format is subject * to change in future releases and should not be relied upon for persisting * instances of this class. * * @since 1.2 */ @SuppressWarnings("serial") public class StandardCategoryLabelGenerator, R extends Comparable, C extends Comparable> implements CategoryLabelGenerator, Serializable { /** * A template string that will show the series, row or column key only. * * @since 1.2 */ public static final String KEY_ONLY_TEMPLATE = "%s"; /** * A template string that will show the key followed by the data total * (for the series, row or column) in brackets, with zero decimal places. */ public static final String TOTAL_TEMPLATE = "%s (%3$,.0f)"; /** * A template string that will show the key followed by the data total * (for the series, row or column) in brackets, with two decimal places. */ public static final String TOTAL_TEMPLATE_2DP = "%s (%3$,.2f)"; /** * The default template string (used in the default constructor, it is * equivalent to {@link #KEY_ONLY_TEMPLATE}). * * @since 1.2 */ public static final String DEFAULT_TEMPLATE = KEY_ONLY_TEMPLATE; /** The template. */ private String template; /** * The default constructor. */ public StandardCategoryLabelGenerator() { this(DEFAULT_TEMPLATE); } /** * Creates a new instance with the specified template string (which will * be passed to a {@code java.util.Formatter} instance when generating * labels). See the class description for an explanation of the values * that are available for use in the template string. * * @param template the template ({@code null} not permitted). */ public StandardCategoryLabelGenerator(String template) { Args.nullNotPermitted(template, "template"); this.template = template; } /** * Generates the label for one series in a category chart. * * @param dataset the dataset ({@code null} not permitted). * @param seriesKey the key ({@code null} not permitted). * * @return The label (never {@code null} for this implementation). */ @Override public String generateSeriesLabel(CategoryDataset3D dataset, S seriesKey) { Args.nullNotPermitted(dataset, "dataset"); Args.nullNotPermitted(seriesKey, "seriesKey"); Formatter formatter = new Formatter(new StringBuilder()); int count = DataUtils.count(dataset, seriesKey); double total = DataUtils.total(dataset, seriesKey); formatter.format(this.template, seriesKey, count, total); String result = formatter.toString(); formatter.close(); return result; } /** * Generates a label for one row in a {@link CategoryDataset3D}. * * @param dataset the dataset ({@code null} not permitted). * @param rowKey the key ({@code null} not permitted). * * @return The row label (possibly {@code null}). */ @Override public String generateRowLabel(CategoryDataset3D dataset, R rowKey) { Args.nullNotPermitted(dataset, "dataset"); Args.nullNotPermitted(rowKey, "rowKey"); Formatter formatter = new Formatter(new StringBuilder()); int count = DataUtils.countForRow(dataset, rowKey); double total = DataUtils.totalForRow(dataset, rowKey); formatter.format(this.template, rowKey, count, total); String result = formatter.toString(); formatter.close(); return result; } /** * Generates a label for one column in a {@link CategoryDataset3D}. * * @param dataset the dataset ({@code null} not permitted). * @param columnKey the key ({@code null} not permitted). * * @return The column label (possibly {@code null}). */ @Override public String generateColumnLabel(CategoryDataset3D dataset, C columnKey) { Args.nullNotPermitted(dataset, "dataset"); Args.nullNotPermitted(columnKey, "columnKey"); Formatter formatter = new Formatter(new StringBuilder()); int count = DataUtils.countForColumn(dataset, columnKey); double total = DataUtils.totalForColumn(dataset, columnKey); formatter.format(this.template, columnKey, count, total); String result = formatter.toString(); formatter.close(); return result; } /** * Tests this label generator for equality with an arbitrary object. * * @param obj the object ({@code null} permitted). * * @return A boolean. */ @Override public boolean equals(Object obj) { if (obj == this) { return true; } if (!(obj instanceof StandardCategoryLabelGenerator)) { return false; } StandardCategoryLabelGenerator that = (StandardCategoryLabelGenerator) obj; if (!this.template.equals(that.template)) { return false; } return true; } @Override public int hashCode() { return this.template.hashCode(); } } orson-charts-2.1.0/src/main/java/org/jfree/chart3d/label/StandardPieLabelGenerator.java000066400000000000000000000141041417331271500307350ustar00rootroot00000000000000/* =========================================================== * Orson Charts : a 3D chart library for the Java(tm) platform * =========================================================== * * (C)opyright 2013-2022, by David Gilbert. All rights reserved. * * https://github.com/jfree/orson-charts * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . * * [Oracle and Java are registered trademarks of Oracle and/or its affiliates. * Other names may be trademarks of their respective owners.] * * If you do not wish to be bound by the terms of the GPL, an alternative * commercial license can be purchased. For details, please see visit the * Orson Charts home page: * * http://www.object-refinery.com/orsoncharts/index.html * */ package org.jfree.chart3d.label; import java.io.Serializable; import java.util.Formatter; import org.jfree.chart3d.data.DataUtils; import org.jfree.chart3d.data.PieDataset3D; import org.jfree.chart3d.internal.Args; /** * A default implementation of the {@link PieLabelGenerator} interface. The * implementation uses a {@link java.util.Formatter} instance to generate * the labels. Three values are passed to the formatter: (1) the key for * the current pie section, (2) the data value for the section (as a * {@code Double}, possibly {@code null}) and (3) the calculated * percentage value (as a {@code Double}, {@code Double.NaN} if the * value is {@code null}). *

* NOTE: This class is serializable, but the serialization format is subject * to change in future releases and should not be relied upon for persisting * instances of this class. * * @since 1.2 */ @SuppressWarnings("serial") public class StandardPieLabelGenerator implements PieLabelGenerator, Serializable { /** * A template string that will show the section key only. * * @since 1.2 */ public static final String KEY_ONLY_TEMPLATE = "%s"; /** * A template string that will show the section key followed by the * percentage in brackets (with zero decimal places). * * @since 1.2 */ public static final String PERCENT_TEMPLATE = "%s (%3$,.0f%%)"; /** * A template string that will show the section key followed by the * percentage in brackets (with two decimal places precision). * * @since 1.2 */ public static final String PERCENT_TEMPLATE_2DP = "%s (%3$,.2f%%)"; /** * A template string that will show the section key followed by the * value in brackets (with zero decimal places precision). * * @since 1.2 */ public static final String VALUE_TEMPLATE = "%s (%2$,.0f)"; /** * A template string that will show the section key followed by the * value in brackets (with two decimal places precision). * * @since 1.2 */ public static final String VALUE_TEMPLATE_2DP = "%s (%2$,.2f)"; /** * The default template string (used in the default constructor, it is * equivalent to {@link #PERCENT_TEMPLATE}). * * @since 1.2 */ public static final String DEFAULT_TEMPLATE = PERCENT_TEMPLATE; /** The label template. */ private String template; /** * The default constructor, uses {@link #DEFAULT_TEMPLATE} for the * template string. */ public StandardPieLabelGenerator() { this(DEFAULT_TEMPLATE); } /** * Creates a new instance with the specified template string (which will * be passed to a {@code java.util.Formatter} instance when generating * labels). See the class description for an explanation of the values * that are available for use in the template string. * * @param template the template ({@code null} not permitted). */ public StandardPieLabelGenerator(String template) { Args.nullNotPermitted(template, "template"); this.template = template; } /** * Generates the label for one section in a pie chart. * * @param dataset the dataset ({@code null} not permitted). * @param key the key ({@code null} not permitted). * * @return The label (never {@code null} for this implementation). */ @Override @SuppressWarnings("unchecked") public String generateLabel(PieDataset3D dataset, Comparable key) { Args.nullNotPermitted(dataset, "dataset"); Args.nullNotPermitted(key, "key"); Formatter formatter = new Formatter(new StringBuilder()); Number value = (Number) dataset.getValue(key); Number percent = Double.NaN; if (value != null) { double total = DataUtils.total(dataset); percent = 100.0 * value.doubleValue() / total; } formatter.format(this.template, key, value, percent); String result = formatter.toString(); formatter.close(); return result; } /** * Tests this label generator for equality with an arbitrary object. * * @param obj the object ({@code null} permitted). * * @return A boolean. */ @Override public boolean equals(Object obj) { if (obj == this) { return true; } if (!(obj instanceof StandardPieLabelGenerator)) { return false; } StandardPieLabelGenerator that = (StandardPieLabelGenerator) obj; if (!this.template.equals(that.template)) { return false; } return true; } @Override public int hashCode() { return this.template.hashCode(); } } orson-charts-2.1.0/src/main/java/org/jfree/chart3d/label/StandardXYZItemLabelGenerator.java000066400000000000000000000140631417331271500315350ustar00rootroot00000000000000/* =========================================================== * Orson Charts : a 3D chart library for the Java(tm) platform * =========================================================== * * (C)opyright 2013-2022, by David Gilbert. All rights reserved. * * https://github.com/jfree/orson-charts * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . * * [Oracle and Java are registered trademarks of Oracle and/or its affiliates. * Other names may be trademarks of their respective owners.] * * If you do not wish to be bound by the terms of the GPL, an alternative * commercial license can be purchased. For details, please see visit the * Orson Charts home page: * * http://www.object-refinery.com/orsoncharts/index.html * */ package org.jfree.chart3d.label; import java.io.Serializable; import java.util.Formatter; import org.jfree.chart3d.data.xyz.XYZDataset; import org.jfree.chart3d.data.xyz.XYZItemKey; import org.jfree.chart3d.interaction.XYZDataItemSelection; import org.jfree.chart3d.internal.Args; /** * A default implementation of the {@link XYZItemLabelGenerator} interface. * The implementation uses a {@link java.util.Formatter} instance to generate * the item labels. Four values are passed to the formatter for possible * inclusion in the resulting label: (1) the key for the series, * (2) the x-value (3) the y-value and (4) the z-value. *

* NOTE: This class is serializable, but the serialization format is subject * to change in future releases and should not be relied upon for persisting * instances of this class. * * @since 1.3 */ @SuppressWarnings("serial") public class StandardXYZItemLabelGenerator implements XYZItemLabelGenerator, Serializable { /** * A label template that will display the series key followed by the * (x, y, z) coordinates with 3 decimal places. */ public static final String KEY_AND_COORDS_3DP_TEMPLATE = "%s (%2$.3f, %3$.3f, %4$.3f)"; /** * A label template that will display the (x, y, z) coordinates with 3 * decimal places. */ public static final String COORDS_3DP_TEMPLATE = "(%2$.3f, %3$.3f, %4$.3f)"; /** The default label template. */ public static final String DEFAULT_TEMPLATE = KEY_AND_COORDS_3DP_TEMPLATE; /** The label template. */ private String template; private XYZDataItemSelection itemSelection; /** * The default constructor. */ public StandardXYZItemLabelGenerator() { this(DEFAULT_TEMPLATE); } /** * Creates a new instance with the specified label template. * * @param template the label template ({@code null} not permitted). */ public StandardXYZItemLabelGenerator(String template) { Args.nullNotPermitted(template, "template"); this.template = template; this.itemSelection = null; } /** * Returns the item selection (if this is non-{@code null}, labels * will only be generated for the items in the selection). * * @return The item selection (possibly {@code null}). */ public XYZDataItemSelection getItemSelection() { return this.itemSelection; } /** * Sets the item selection, which can be used to specify a subset of the * data items that should have item labels generated. If this is set to * {@code null} then item labels will be generated for all items. * * @param selection the selection ({@code null} permitted). */ public void setItemSelection(XYZDataItemSelection selection) { this.itemSelection = selection; } /** * Generates a label for the specified data item. * * @param dataset the dataset ({@code null} not permitted). * @param seriesKey the series key ({@code null} not permitted). * * @return The series label (possibly {@code null}). */ @Override @SuppressWarnings("unchecked") public String generateItemLabel(XYZDataset dataset, Comparable seriesKey, int itemIndex) { Args.nullNotPermitted(dataset, "dataset"); Args.nullNotPermitted(seriesKey, "seriesKey"); if (this.itemSelection != null) { XYZItemKey key = new XYZItemKey(seriesKey, itemIndex); if (!this.itemSelection.isSelected(key)) { return null; } } int seriesIndex = dataset.getSeriesIndex(seriesKey); Formatter formatter = new Formatter(new StringBuilder()); double x = dataset.getX(seriesIndex, itemIndex); double y = dataset.getY(seriesIndex, itemIndex); double z = dataset.getZ(seriesIndex, itemIndex); formatter.format(this.template, seriesKey, x, y, z); String result = formatter.toString(); formatter.close(); return result; } /** * Tests this label generator for equality with an arbitrary object. * * @param obj the object ({@code null} permitted). * * @return A boolean. */ @Override public boolean equals(Object obj) { if (obj == this) { return true; } if (!(obj instanceof StandardXYZItemLabelGenerator)) { return false; } StandardXYZItemLabelGenerator that = (StandardXYZItemLabelGenerator) obj; if (!this.template.equals(that.template)) { return false; } return true; } @Override public int hashCode() { return this.template.hashCode(); } } orson-charts-2.1.0/src/main/java/org/jfree/chart3d/label/StandardXYZLabelGenerator.java000066400000000000000000000125211417331271500307130ustar00rootroot00000000000000/* =========================================================== * Orson Charts : a 3D chart library for the Java(tm) platform * =========================================================== * * (C)opyright 2013-2022, by David Gilbert. All rights reserved. * * https://github.com/jfree/orson-charts * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . * * [Oracle and Java are registered trademarks of Oracle and/or its affiliates. * Other names may be trademarks of their respective owners.] * * If you do not wish to be bound by the terms of the GPL, an alternative * commercial license can be purchased. For details, please see visit the * Orson Charts home page: * * http://www.object-refinery.com/orsoncharts/index.html * */ package org.jfree.chart3d.label; import java.io.Serializable; import java.util.Formatter; import org.jfree.chart3d.data.DataUtils; import org.jfree.chart3d.data.xyz.XYZDataset; import org.jfree.chart3d.internal.Args; /** * A default implementation of the {@link XYZLabelGenerator} interface. * The implementation uses a {@link java.util.Formatter} instance to generate * the labels, which are typically used as the series labels in the chart * legend. Three values are passed to the formatter for possible inclusion * in the resulting label: (1) the key for the series, (2) the count for the * number of items in the series (as an {@code Integer}) and (3) the total * of the non-{@code NaN} values in the series (as a {@code Double}). *

* NOTE: This class is serializable, but the serialization format is subject * to change in future releases and should not be relied upon for persisting * instances of this class. * * @since 1.2 */ @SuppressWarnings("serial") public class StandardXYZLabelGenerator implements XYZLabelGenerator, Serializable { /** A label template that will display the series key only. */ public static final String KEY_ONLY_TEMPLATE = "%s"; /** * A label template that will display the series key followed by the * total of the data items for the series (in brackets) with zero decimal * places. */ public static final String TOTAL_TEMPLATE = "%s (%3$,.0f)"; /** * A label template that will display the series key followed by the * total of the data items for the series (in brackets) with zero decimal * places. */ public static final String TOTAL_TEMPLATE_2DP = "%s (%3$,.2f)"; /** * A label template that will display the series key followed by the * number of data items for the series (in brackets). */ public static final String COUNT_TEMPLATE = "%s (%2$,d)"; /** The default label template. */ public static final String DEFAULT_TEMPLATE = KEY_ONLY_TEMPLATE; /** The label template. */ private String template; /** * The default constructor. */ public StandardXYZLabelGenerator() { this(DEFAULT_TEMPLATE); } /** * Creates a new instance with the specified label template. * * @param template the label template ({@code null} not permitted). */ public StandardXYZLabelGenerator(String template) { Args.nullNotPermitted(template, "template"); this.template = template; } /** * Generates a series label. * * @param dataset the dataset ({@code null} not permitted). * @param seriesKey the series key ({@code null} not permitted). * * @return The series label (possibly {@code null}). */ @Override public > String generateSeriesLabel( XYZDataset dataset, S seriesKey) { Args.nullNotPermitted(dataset, "dataset"); Args.nullNotPermitted(seriesKey, "seriesKey"); Formatter formatter = new Formatter(new StringBuilder()); int count = dataset.getItemCount(dataset.getSeriesIndex(seriesKey)); double total = DataUtils.total(dataset, seriesKey); formatter.format(this.template, seriesKey, count, total); String result = formatter.toString(); formatter.close(); return result; } /** * Tests this label generator for equality with an arbitrary object. * * @param obj the object ({@code null} permitted). * * @return A boolean. */ @Override public boolean equals(Object obj) { if (obj == this) { return true; } if (!(obj instanceof StandardXYZLabelGenerator)) { return false; } StandardXYZLabelGenerator that = (StandardXYZLabelGenerator) obj; if (!this.template.equals(that.template)) { return false; } return true; } @Override public int hashCode() { return this.template.hashCode(); } } orson-charts-2.1.0/src/main/java/org/jfree/chart3d/label/XYZItemLabelGenerator.java000066400000000000000000000043101417331271500300460ustar00rootroot00000000000000/* =========================================================== * Orson Charts : a 3D chart library for the Java(tm) platform * =========================================================== * * (C)opyright 2013-2022, by David Gilbert. All rights reserved. * * https://github.com/jfree/orson-charts * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . * * [Oracle and Java are registered trademarks of Oracle and/or its affiliates. * Other names may be trademarks of their respective owners.] * * If you do not wish to be bound by the terms of the GPL, an alternative * commercial license can be purchased. For details, please see visit the * Orson Charts home page: * * http://www.object-refinery.com/orsoncharts/index.html * */ package org.jfree.chart3d.label; import org.jfree.chart3d.data.xyz.XYZDataset; /** * A label generator for data items in XYZ charts (this can be used for * tooltips and item labels). The ({@link StandardXYZItemLabelGenerator}) * class provides the default implementation. *

* Implementations of this interface are expected to support cloning and * serialization. * * @since 1.3 */ public interface XYZItemLabelGenerator { /** * Generates an item label for one data item in an {@link XYZDataset}. * * @param dataset the dataset ({@code null} not permitted). * @param seriesKey the series key ({@code null} not permitted). * @param itemIndex the item index. * * @return The item label (possibly {@code null}). */ String generateItemLabel(XYZDataset dataset, Comparable seriesKey, int itemIndex); } orson-charts-2.1.0/src/main/java/org/jfree/chart3d/label/XYZLabelGenerator.java000066400000000000000000000041171417331271500272340ustar00rootroot00000000000000/* =========================================================== * Orson Charts : a 3D chart library for the Java(tm) platform * =========================================================== * * (C)opyright 2013-2022, by David Gilbert. All rights reserved. * * https://github.com/jfree/orson-charts * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . * * [Oracle and Java are registered trademarks of Oracle and/or its affiliates. * Other names may be trademarks of their respective owners.] * * If you do not wish to be bound by the terms of the GPL, an alternative * commercial license can be purchased. For details, please see visit the * Orson Charts home page: * * http://www.object-refinery.com/orsoncharts/index.html * */ package org.jfree.chart3d.label; import org.jfree.chart3d.data.xyz.XYZDataset; /** * A label generator for XYZ charts, used to create labels for the chart * legend. The ({@link StandardXYZLabelGenerator}) class provides the default * implementation. * * @since 1.2 */ public interface XYZLabelGenerator { /** * Generates a label for one series in a {@link XYZDataset}. * * @param The type of the series keys in the dataset. * @param dataset the dataset ({@code null} not permitted). * @param seriesKey the series key ({@code null} not permitted). * * @return The series label (possibly {@code null}). */ > String generateSeriesLabel( XYZDataset dataset, S seriesKey); }orson-charts-2.1.0/src/main/java/org/jfree/chart3d/label/package-info.java000066400000000000000000000001151417331271500262510ustar00rootroot00000000000000/** * Classes related to chart labels. */ package org.jfree.chart3d.label; orson-charts-2.1.0/src/main/java/org/jfree/chart3d/legend/000077500000000000000000000000001417331271500232445ustar00rootroot00000000000000orson-charts-2.1.0/src/main/java/org/jfree/chart3d/legend/ColorScaleElement.java000066400000000000000000000340661417331271500274600ustar00rootroot00000000000000/* =========================================================== * Orson Charts : a 3D chart library for the Java(tm) platform * =========================================================== * * (C)opyright 2013-2022, by David Gilbert. All rights reserved. * * https://github.com/jfree/orson-charts * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . * * [Oracle and Java are registered trademarks of Oracle and/or its affiliates. * Other names may be trademarks of their respective owners.] * * If you do not wish to be bound by the terms of the GPL, an alternative * commercial license can be purchased. For details, please see visit the * Orson Charts home page: * * http://www.object-refinery.com/orsoncharts/index.html * */ package org.jfree.chart3d.legend; import java.awt.Shape; import java.util.ArrayList; import java.awt.Font; import java.awt.Graphics2D; import java.awt.Insets; import java.awt.BasicStroke; import java.awt.Color; import java.awt.geom.Dimension2D; import java.awt.geom.Rectangle2D; import java.util.List; import java.util.Map; import java.awt.FontMetrics; import java.text.DecimalFormat; import java.text.NumberFormat; import org.jfree.chart3d.Orientation; import org.jfree.chart3d.data.Range; import org.jfree.chart3d.graphics2d.Fit2D; import org.jfree.chart3d.graphics2d.TextAnchor; import org.jfree.chart3d.internal.Args; import org.jfree.chart3d.internal.TextUtils; import org.jfree.chart3d.renderer.ColorScale; import org.jfree.chart3d.table.AbstractTableElement; import org.jfree.chart3d.table.ElementDimension; import org.jfree.chart3d.table.TableElement; import org.jfree.chart3d.table.TableElementOnDraw; import org.jfree.chart3d.table.TableElementVisitor; /** * A {@link TableElement} that displays a {@link ColorScale}. *

* NOTE: This class is serializable, but the serialization format is subject * to change in future releases and should not be relied upon for persisting * instances of this class. * * @since 1.1 */ @SuppressWarnings("serial") public class ColorScaleElement extends AbstractTableElement implements TableElement { /** The color scale. */ private final ColorScale scale; /** The orientation (horizontal or vertical). */ private final Orientation orientation; /** The length of the bar. */ private final double barLength; /** The width of the bar. */ private final double barWidth; /** The gap between the color scale bar and the text labels. */ private final double textOffset; /** The font for the text labels. */ private final Font font; /** The text color. */ private final Color textColor; /** The number formatter. */ private final NumberFormat formatter; /** * Creates a new {@code ColorScaleElement} with the specified * attributes. * * @param scale the color scale ({@code null} not permitted). * @param orientation the orientation ({@code null} not permitted). * @param barWidth the bar width (in Java2D units). * @param barLength the bar length (in Java2D units). * @param font the font ({@code null} not permitted). * @param textColor the text color ({@code null} not permitted). * * @since 1.2 */ public ColorScaleElement(ColorScale scale, Orientation orientation, double barWidth, double barLength, Font font, Color textColor) { super(); Args.nullNotPermitted(scale, "scale"); Args.nullNotPermitted(orientation, "orientation"); Args.nullNotPermitted(font, "font"); this.scale = scale; this.orientation = orientation; this.barWidth = barWidth; this.barLength = barLength; this.textOffset = 2; this.font = font; this.textColor = textColor; this.formatter = new DecimalFormat("0.00"); } /** * Returns the color scale. * * @return The color scale (never {@code null}). */ public ColorScale getColorScale() { return this.scale; } /** * Returns the orientation. * * @return The orientation (never {@code null}). */ public Orientation getOrientation() { return this.orientation; } /** * Returns the bar width. * * @return The bar width. */ public double getBarWidth() { return this.barWidth; } /** * Returns the bar length. * * @return The bar length. */ public double getBarLength() { return this.barLength; } /** * Returns the font used to display the labels on the color scale. * * @return The font (never {@code null}). */ public Font getFont() { return this.font; } /** * Returns the text color. * * @return The text color (never {@code null}). */ public Color getTextColor() { return this.textColor; } /** * Receives a visitor. This is part of a general mechanism to perform * operations on an arbitrary hierarchy of table elements. You will not * normally call this method directly. * * @param visitor the visitor ({@code null} not permitted). * * @since 1.2 */ @Override public void receive(TableElementVisitor visitor) { visitor.visit(this); } /** * Returns the preferred size for this element. * * @param g2 the graphics target. * @param bounds the available drawing space. * * @return The preferred size (never {@code null}). */ @Override public Dimension2D preferredSize(Graphics2D g2, Rectangle2D bounds) { return preferredSize(g2, bounds, null); } /** * Returns the preferred size for this element. * * @param g2 the graphics target. * @param bounds the available drawing space. * @param constraints layout constraints (ignored here). * * @return The preferred size (never {@code null}). */ @Override public Dimension2D preferredSize(Graphics2D g2, Rectangle2D bounds, Map constraints) { g2.setFont(this.font); FontMetrics fm = g2.getFontMetrics(); Range r = this.scale.getRange(); String minStr = this.formatter.format(r.getMin()); String maxStr = this.formatter.format(r.getMax()); Rectangle2D minStrBounds = TextUtils.getTextBounds(minStr, fm); Rectangle2D maxStrBounds = TextUtils.getTextBounds(maxStr, fm); double maxStrWidth = Math.max(minStrBounds.getWidth(), maxStrBounds.getWidth()); Insets insets = getInsets(); double w, h; if (this.orientation == Orientation.HORIZONTAL) { w = Math.min(this.barLength + insets.left + insets.right, bounds.getWidth()); h = Math.min(insets.top + this.barWidth + this.textOffset + minStrBounds.getHeight() + insets.bottom, bounds.getHeight()); } else { w = Math.min(insets.left + this.barWidth + this.textOffset + maxStrWidth + insets.right, bounds.getWidth()); h = Math.min(insets.top + this.barLength + this.textOffset + minStrBounds.getHeight() + insets.bottom, bounds.getHeight()); } return new ElementDimension(w, h); } @Override public List layoutElements(Graphics2D g2, Rectangle2D bounds, Map constraints) { List result = new ArrayList<>(1); Dimension2D prefDim = preferredSize(g2, bounds); Fit2D fitter = Fit2D.getNoScalingFitter(getRefPoint()); Rectangle2D dest = fitter.fit(prefDim, bounds); result.add(dest); return result; } /** * Draws the element within the specified bounds. * * @param g2 the graphics target ({@code null} not permitted). * @param bounds the bounds ({@code null} not permitted). */ @Override public void draw(Graphics2D g2, Rectangle2D bounds) { draw(g2, bounds, null); } /** * Draws the element within the specified bounds. * * @param g2 the graphics target ({@code null} not permitted). * @param bounds the bounds ({@code null} not permitted). * @param onDrawHandler receives notification before and after the element * is drawn ({@code null} permitted); * * @since 1.3 */ @Override public void draw(Graphics2D g2, Rectangle2D bounds, TableElementOnDraw onDrawHandler) { if (onDrawHandler != null) { onDrawHandler.beforeDraw(this, g2, bounds); } Shape savedClip = g2.getClip(); g2.clip(bounds); List layoutInfo = layoutElements(g2, bounds, null); Rectangle2D dest = layoutInfo.get(0); if (getBackground() != null) { getBackground().fill(g2, dest); } g2.setFont(this.font); FontMetrics fm = g2.getFontMetrics(); Range r = this.scale.getRange(); String minStr = this.formatter.format(r.getMin()); String maxStr = this.formatter.format(r.getMax()); Rectangle2D minStrBounds = TextUtils.getTextBounds(minStr, fm); Rectangle2D maxStrBounds = TextUtils.getTextBounds(maxStr, fm); Insets insets = getInsets(); if (this.orientation == Orientation.HORIZONTAL) { double x0 = dest.getX() + insets.left + minStrBounds.getWidth() / 2.0; double x1 = dest.getMaxX() - insets.right - maxStrBounds.getWidth() / 2.0; double y0 = dest.getY() + insets.top; double y1 = y0 + this.barWidth; drawHorizontalScale(this.scale, g2, new Rectangle2D.Double( (int) x0, (int) y0, (int) (x1 - x0), (int) this.barWidth)); // fill the bar with the color scale g2.setPaint(this.textColor); TextUtils.drawAlignedString(minStr, g2, (float) x0, (float) (y1 + this.textOffset), TextAnchor.TOP_CENTER); TextUtils.drawAlignedString(maxStr, g2, (float) x1, (float) (y1 + this.textOffset), TextAnchor.TOP_CENTER); } else { // VERTICAL double maxStrWidth = Math.max(minStrBounds.getWidth(), maxStrBounds.getWidth()); double x1 = dest.getMaxX() - insets.right - maxStrWidth - this.textOffset; double x0 = x1 - this.barWidth; double y0 = dest.getY() + insets.top + maxStrBounds.getHeight() / 2.0; double y1 = y0 + this.barLength; drawVerticalScale(this.scale, g2, new Rectangle2D.Double( (int) x0, (int) y0, (int) (x1 - x0), (int) this.barLength)); g2.setPaint(this.textColor); TextUtils.drawAlignedString(minStr, g2, (float) (x1 + this.textOffset), (float) y1, TextAnchor.HALF_ASCENT_LEFT); TextUtils.drawAlignedString(maxStr, g2, (float) (x1 + this.textOffset), (float) y0, TextAnchor.HALF_ASCENT_LEFT); } g2.setClip(savedClip); if (onDrawHandler != null) { onDrawHandler.afterDraw(this, g2, bounds); } } /** * Draws the color scale horizontally within the specified bounds. * * @param colorScale the color scale. * @param g2 the graphics target. * @param bounds the bounds. */ private void drawHorizontalScale(ColorScale colorScale, Graphics2D g2, Rectangle2D bounds) { g2.setStroke(new BasicStroke(1.0f)); for (int x = (int) bounds.getX(); x < bounds.getMaxX(); x++) { double p = (x - bounds.getX()) / bounds.getWidth(); double value = colorScale.getRange().value(p); g2.setColor(colorScale.valueToColor(value)); g2.drawLine(x, (int) bounds.getMinY(), x, (int) bounds.getMaxY()); } } /** * Draws the color scale vertically within the specified bounds. * * @param colorScale the color scale. * @param g2 the graphics target. * @param bounds the bounds. */ private void drawVerticalScale(ColorScale colorScale, Graphics2D g2, Rectangle2D bounds) { g2.setStroke(new BasicStroke(1.0f)); for (int y = (int) bounds.getY(); y < bounds.getMaxY(); y++) { double p = (y - bounds.getY()) / bounds.getHeight(); double value = colorScale.getRange().value(1 - p); g2.setColor(this.scale.valueToColor(value)); g2.drawLine((int) bounds.getX(), y, (int) bounds.getMaxX(), y); } } @Override public boolean equals(Object obj) { if (obj == this) { return true; } if (!(obj instanceof ColorScaleElement)) { return false; } ColorScaleElement that = (ColorScaleElement) obj; if (!this.scale.equals(that.scale)) { return false; } if (!this.orientation.equals(that.orientation)) { return false; } if (this.barLength != that.barLength) { return false; } if (this.barWidth != that.barWidth) { return false; } if (!this.font.equals(that.font)) { return false; } return super.equals(obj); } } orson-charts-2.1.0/src/main/java/org/jfree/chart3d/legend/ColorScaleLegendBuilder.java000066400000000000000000000171551417331271500305740ustar00rootroot00000000000000/* =========================================================== * Orson Charts : a 3D chart library for the Java(tm) platform * =========================================================== * * (C)opyright 2013-2022, by David Gilbert. All rights reserved. * * http://www.object-refinery.com/orsoncharts/index.html * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . * * [Oracle and Java are registered trademarks of Oracle and/or its affiliates. * Other names may be trademarks of their respective owners.] * * If you do not wish to be bound by the terms of the GPL, an alternative * commercial license can be purchased. For details, please see visit the * Orson Charts home page: * * http://www.object-refinery.com/orsoncharts/index.html * */ package org.jfree.chart3d.legend; import java.io.Serializable; import org.jfree.chart3d.Chart3D; import org.jfree.chart3d.Orientation; import org.jfree.chart3d.graphics2d.Anchor2D; import org.jfree.chart3d.plot.CategoryPlot3D; import org.jfree.chart3d.plot.Plot3D; import org.jfree.chart3d.plot.XYZPlot; import org.jfree.chart3d.renderer.ColorScale; import org.jfree.chart3d.renderer.ColorScaleRenderer; import org.jfree.chart3d.renderer.FixedColorScale; import org.jfree.chart3d.renderer.category.CategoryRenderer3D; import org.jfree.chart3d.renderer.xyz.XYZRenderer; import org.jfree.chart3d.style.ChartStyle; import org.jfree.chart3d.table.TableElement; /** * A legend builder that creates a legend representing a {@link ColorScale}. * This builder will only create a legend if the plot uses a renderer * that implements the {@link ColorScaleRenderer} interface. *

* The orientation and anchor point for the legend are properties of the * {@link Chart3D} class. *

* NOTE: This class is serializable, but the serialization format is subject * to change in future releases and should not be relied upon for persisting * instances of this class. * * @since 1.1 */ @SuppressWarnings("serial") public class ColorScaleLegendBuilder implements LegendBuilder, Serializable { /** The width of the bar showing the color scale (in Java2D units). */ private double barWidth; /** The length of the bar showing the color scale (in Java2D units). */ private double barLength; /** * A flag to determine whether or not FixedColorScale is ignored (defaults * to {@code true}). */ private boolean ignoreFixedColorScale; /** * Creates a new instance. */ public ColorScaleLegendBuilder() { this.barWidth = 16.0; this.barLength = 140.0; this.ignoreFixedColorScale = true; } /** * Returns the width of the bar displaying the color scale. * * @return The width (in Java2D units). */ public double getBarWidth() { return this.barWidth; } /** * Sets the width of the bar displaying the color scale. * * @param width the width (in Java2D units). */ public void setBarWidth(double width) { this.barWidth = width; } /** * Returns the length of the bar displaying the color scale. * * @return The length (in Java2D units). */ public double getBarLength() { return this.barLength; } /** * Sets the length of the bar displaying the color scale. * * @param length the length (in Java2D units). */ public void setBarLength(double length) { this.barLength = length; } /** * Returns the flag that controls whether or not a {@link FixedColorScale} * will be ignored for the purposes of generating a legend. * * @return A boolean. */ public boolean getIgnoreFixedColorScale() { return this.ignoreFixedColorScale; } /** * Sets the flag that controls whether or not a {@link FixedColorScale} * will be ignored for the purposes of generating a legend. * * @param ignore the new flag value. */ public void setIgnoreFixedColorScale(boolean ignore) { this.ignoreFixedColorScale = ignore; } /** * Creates a new color scale legend with the specified orientation. * If the plot does not use a renderer that implements * {@link ColorScaleRenderer} then this method will return {@code null} * and no legend will be drawn on the chart. * * @param plot the plot ({@code null} not permitted). * @param anchor the anchor ({@code null} not permitted). * @param orientation the orientation ({@code null} not permitted). * @param style the chart style ({@code null} not permitted). * * @return A color scale legend (possibly {@code null}). */ @Override public TableElement createLegend(Plot3D plot, Anchor2D anchor, Orientation orientation, ChartStyle style) { ColorScaleRenderer renderer = null; if (plot instanceof CategoryPlot3D) { CategoryRenderer3D r = ((CategoryPlot3D) plot).getRenderer(); if (r instanceof ColorScaleRenderer) { renderer = (ColorScaleRenderer) r; } } else if (plot instanceof XYZPlot) { XYZRenderer r = ((XYZPlot) plot).getRenderer(); if (r instanceof ColorScaleRenderer) { renderer = (ColorScaleRenderer) r; } } if (renderer == null) { return null; } // it doesn't make much sense to display a color scale legend for a // FixedColorScale so we check for that and ignore it (unless the // developer switched the ignoreFixedColorScale flag, in which case // you can have your legend)... if (this.ignoreFixedColorScale && renderer.getColorScale() instanceof FixedColorScale) { return null; } return createColorScaleLegend(renderer, orientation, anchor, style); } private TableElement createColorScaleLegend(ColorScaleRenderer r, Orientation orientation, Anchor2D anchor, ChartStyle style) { ColorScale scale = r.getColorScale(); ColorScaleElement element = new ColorScaleElement(scale, orientation, this.barWidth, this.barLength, style.getLegendItemFont(), style.getLegendItemColor()); element.setBackgroundColor(style.getLegendItemBackgroundColor()); element.setRefPoint(anchor.getRefPt()); return element; } /** * Tests this builder for equality with an arbitrary object. * * @param obj the object ({@code null} permitted). * * @return A boolean. */ @Override public boolean equals(Object obj) { if (obj == this) { return true; } if (!(obj instanceof ColorScaleLegendBuilder)) { return false; } ColorScaleLegendBuilder that = (ColorScaleLegendBuilder) obj; if (this.barWidth != that.barWidth) { return false; } if (this.barLength != that.barLength) { return false; } return true; } } orson-charts-2.1.0/src/main/java/org/jfree/chart3d/legend/LegendAnchor.java000066400000000000000000000055731417331271500264520ustar00rootroot00000000000000/* =========================================================== * Orson Charts : a 3D chart library for the Java(tm) platform * =========================================================== * * (C)opyright 2013-2022, by David Gilbert. All rights reserved. * * https://github.com/jfree/orson-charts * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . * * [Oracle and Java are registered trademarks of Oracle and/or its affiliates. * Other names may be trademarks of their respective owners.] * * If you do not wish to be bound by the terms of the GPL, an alternative * commercial license can be purchased. For details, please see visit the * Orson Charts home page: * * http://www.object-refinery.com/orsoncharts/index.html * */ package org.jfree.chart3d.legend; import org.jfree.chart3d.TitleAnchor; import org.jfree.chart3d.graphics2d.Anchor2D; /** * Predefined legend anchor points, provided for convenience. The anchor * points are simply instances of the {@link Anchor2D} class. */ public final class LegendAnchor { /** * An anchor point at the top-left of the chart area. */ public static final Anchor2D TOP_LEFT = TitleAnchor.TOP_LEFT; /** * An anchor point at the top-right of the chart area. */ public static final Anchor2D TOP_RIGHT = TitleAnchor.TOP_RIGHT; /** * An anchor point at the top-center of the chart area. */ public static final Anchor2D TOP_CENTER = TitleAnchor.TOP_CENTER; /** * An anchor point at the center-left of the chart area. */ public static final Anchor2D CENTER_LEFT = TitleAnchor.CENTER_LEFT; /** * An anchor point at the center-right of the chart area. */ public static final Anchor2D CENTER_RIGHT = TitleAnchor.CENTER_RIGHT; /** * An anchor point at the bottom-center of the chart area. */ public static final Anchor2D BOTTOM_CENTER = TitleAnchor.BOTTOM_CENTER; /** * An anchor point at the bottom-left of the chart area. */ public static final Anchor2D BOTTOM_LEFT = TitleAnchor.BOTTOM_LEFT; /** * An anchor point at the bottom-right of the chart area. */ public static final Anchor2D BOTTOM_RIGHT = TitleAnchor.BOTTOM_RIGHT; private LegendAnchor() { // no need to instantiate this } } orson-charts-2.1.0/src/main/java/org/jfree/chart3d/legend/LegendBuilder.java000066400000000000000000000055201417331271500266160ustar00rootroot00000000000000/* =========================================================== * Orson Charts : a 3D chart library for the Java(tm) platform * =========================================================== * * (C)opyright 2013-2022, by David Gilbert. All rights reserved. * * https://github.com/jfree/orson-charts * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . * * [Oracle and Java are registered trademarks of Oracle and/or its affiliates. * Other names may be trademarks of their respective owners.] * * If you do not wish to be bound by the terms of the GPL, an alternative * commercial license can be purchased. For details, please see visit the * Orson Charts home page: * * http://www.object-refinery.com/orsoncharts/index.html * */ package org.jfree.chart3d.legend; import org.jfree.chart3d.Chart3D; import org.jfree.chart3d.Orientation; import org.jfree.chart3d.graphics2d.Anchor2D; import org.jfree.chart3d.plot.Plot3D; import org.jfree.chart3d.style.ChartStyle; import org.jfree.chart3d.table.TableElement; /** * A legend builder is responsible for creating a legend for a chart. The API * has been kept to a minimum intentionally, so as not to overly constrain * developers that want to implement a custom legend builder. The * {@code get/setItemFont()} methods have been added for convenience * because changing the font of the legend item text is a very common * operation. *

* Classes that implement this interface should also implement * {@code java.io.Serializable} if you intend to serialize and deserialize * chart objects. * * @see Chart3D#setLegendBuilder(LegendBuilder) */ public interface LegendBuilder { /** * Creates a legend for the specified plot. If this method returns * {@code null}, no legend will be displayed. * * @param plot the plot ({@code null} not permitted). * @param anchor the anchor ({@code null} not permitted). * @param orientation the legend orientation ({@code null} not * permitted). * @param style the style ({@code null} not permitted). * * @return A legend (possibly {@code null}). * * @since 1.2 */ TableElement createLegend(Plot3D plot, Anchor2D anchor, Orientation orientation, ChartStyle style); } orson-charts-2.1.0/src/main/java/org/jfree/chart3d/legend/LegendItemInfo.java000066400000000000000000000060601417331271500267420ustar00rootroot00000000000000/* =========================================================== * Orson Charts : a 3D chart library for the Java(tm) platform * =========================================================== * * (C)opyright 2013-2022, by David Gilbert. All rights reserved. * * https://github.com/jfree/orson-charts * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . * * [Oracle and Java are registered trademarks of Oracle and/or its affiliates. * Other names may be trademarks of their respective owners.] * * If you do not wish to be bound by the terms of the GPL, an alternative * commercial license can be purchased. For details, please see visit the * Orson Charts home page: * * http://www.object-refinery.com/orsoncharts/index.html * */ package org.jfree.chart3d.legend; import java.awt.Shape; import java.util.Map; import java.awt.Color; import org.jfree.chart3d.plot.Plot3D; /** * Information about an item (typically a data series) that can be displayed * in a legend. All plots will return a list of these, to be used in the * construction of a chart legend, via the {@link Plot3D#getLegendInfo()} * method. */ public interface LegendItemInfo { /** * Returns the series key. * * @return The series key (never {@code null}). */ Comparable getSeriesKey(); /** * Returns the series label that will be displayed in the legend. Very * often this is the same as {@code getSeriesKey().toString()}, but * here we have the option to provide some alternative text. * * @return The label (never {@code null}). */ String getLabel(); /** * Returns a longer description of the series (this could be used in * tooltips, for example). * * @return The description (possibly {@code null}). */ String getDescription(); /** * Returns the shape used to represent the series in the legend. This * may be {@code null}, in which case the legend builder should * use a default shape. * * @return The shape (possibly {@code null}). */ Shape getShape(); /** * Returns the color used to represent a series. * * @return The color (never {@code null}). */ Color getColor(); /** * A map containing other properties for the legend item. Not currently * used, but available for future expansion. * * @return A map (never {@code null}). */ Map, Object> getProperties(); } orson-charts-2.1.0/src/main/java/org/jfree/chart3d/legend/StandardLegendBuilder.java000066400000000000000000000355641417331271500303120ustar00rootroot00000000000000/* =========================================================== * Orson Charts : a 3D chart library for the Java(tm) platform * =========================================================== * * (C)opyright 2013-2022, by David Gilbert. All rights reserved. * * https://github.com/jfree/orson-charts * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . * * [Oracle and Java are registered trademarks of Oracle and/or its affiliates. * Other names may be trademarks of their respective owners.] * * If you do not wish to be bound by the terms of the GPL, an alternative * commercial license can be purchased. For details, please see visit the * Orson Charts home page: * * http://www.object-refinery.com/orsoncharts/index.html * */ package org.jfree.chart3d.legend; import java.awt.Color; import java.awt.Font; import java.awt.Shape; import java.util.List; import java.io.Serializable; import org.jfree.chart3d.internal.Args; import org.jfree.chart3d.internal.ObjectUtils; import org.jfree.chart3d.Chart3D; import org.jfree.chart3d.Orientation; import org.jfree.chart3d.graphics2d.Anchor2D; import org.jfree.chart3d.interaction.InteractiveElementType; import org.jfree.chart3d.plot.CategoryPlot3D; import org.jfree.chart3d.plot.PiePlot3D; import org.jfree.chart3d.plot.Plot3D; import org.jfree.chart3d.plot.XYZPlot; import org.jfree.chart3d.style.ChartStyle; import org.jfree.chart3d.table.ContainerElement; import org.jfree.chart3d.table.FlowElement; import org.jfree.chart3d.table.GridElement; import org.jfree.chart3d.table.HAlign; import org.jfree.chart3d.table.ShapeElement; import org.jfree.chart3d.table.TableElement; import org.jfree.chart3d.table.TextElement; import org.jfree.chart3d.table.VAlign; import org.jfree.chart3d.table.VerticalFlowElement; /** * The standard legend builder, which creates a simple legend * with a flow layout and optional header and footer text. *

* NOTE: This class is serializable, but the serialization format is subject * to change in future releases and should not be relied upon for persisting * instances of this class. */ public final class StandardLegendBuilder implements LegendBuilder, Serializable { /** An optional header/title for the legend (can be {@code null}). */ private String header; /** The header alignment (never {@code null}). */ private HAlign headerAlignment; /** An optional footer for the legend (can be {@code null}). */ private String footer; /** The footer alignment (never {@code null}). */ private HAlign footerAlignment; /** * The row alignment (if {@code null}, the row alignment will be * derived from the anchor point). */ private HAlign rowAlignment; /** * The column alignment (if {@code null}, the column alignment will * be derived from the anchor point). */ private VAlign columnAlignment; /** * Creates a builder for a simple legend with no header and no footer. */ public StandardLegendBuilder() { this(null, null); } /** * Creates a builder for a simple legend with the specified header and/or * footer. * * @param header the legend header ({@code null} permitted). * @param footer the legend footer ({@code null} permitted). */ public StandardLegendBuilder(String header, String footer) { this.header = header; this.headerAlignment = HAlign.LEFT; this.footer = footer; this.footerAlignment = HAlign.RIGHT; this.rowAlignment = null; this.columnAlignment = null; } /** * Returns the header text. * * @return The header text (possibly {@code null}). */ public String getHeader() { return this.header; } /** * Sets the header text. * * @param header the header ({@code null} permitted). */ public void setHeader(String header) { this.header = header; } /** * Returns the header alignment. * * @return The header alignment (never {@code null}). */ public HAlign getHeaderAlignment() { return this.headerAlignment; } /** * Sets the header alignment. * * @param align the header alignment ({@code null} not permitted). */ public void setHeaderAlignment(HAlign align) { Args.nullNotPermitted(align, "align"); this.headerAlignment = align; } /** * Returns the footer text. * * @return The footer text (possibly {@code null}). */ public String getFooter() { return this.footer; } /** * Sets the footer text. * * @param footer the footer ({@code null} permitted). */ public void setFooter(String footer) { this.footer = footer; } /** * Returns the footer alignment. * * @return The footer alignment (never {@code null}). */ public HAlign getFooterAlignment() { return this.footerAlignment; } /** * Sets the footer alignment. * * @param align the footer alignment ({@code null} not permitted). */ public void setFooterAlignment(HAlign align) { Args.nullNotPermitted(align, "align"); this.footerAlignment = align; } /** * Returns the row alignment. The default value is {@code null} * which means that the row alignment is derived from the anchor point * (left aligned for anchors on the left side, center alignment for * anchors in the middle, and right aligned for anchors on the right side). * * @return The row alignment (possibly {@code null}). * * @since 1.1 */ public HAlign getRowAlignment() { return this.rowAlignment; } /** * Sets the row alignment (to override the default alignment that is * derived from the legend anchor point). In most circumstances you * should be able to rely on the default behaviour, so leave this * attribute set to {@code null}. * * @param alignment the row alignment ({@code null} permitted). * * @since 1.1 */ public void setRowAlignment(HAlign alignment) { this.rowAlignment = alignment; } /** * Returns the column alignment. The default value is {@code null} * which means that the column alignment is derived from the anchor point * (top aligned for anchors at the top, center alignment for * anchors in the middle, and bottom aligned for anchors at the bottom). * * @return The column alignment (possibly {@code null}). * * @since 1.1 */ public VAlign getColumnAlignment() { return this.columnAlignment; } /** * Sets the column alignment (to override the default alignment that is * derived from the legend anchor point). In most circumstances you * should be able to rely on the default behaviour, so leave this * attribute set to {@code null}. * * @param alignment the column alignment ({@code null} permitted). * * @since 1.1 */ public void setColumnAlignment(VAlign alignment) { this.columnAlignment = alignment; } /** * Creates and returns a legend (instance of {@link TableElement}) that * provides a visual key for the data series in the specified plot. The * plot can be any of the built-in plot types: {@link PiePlot3D}, * {@link CategoryPlot3D} or {@link XYZPlot}. *

* Certain subelements will have the following properties set so that * downstream code is able to identify which elements relate to particular * data series: CLASS : 'LegendItem', SERIES_KEY : the series key. * * @param plot the plot ({@code null} not permitted). * @param anchor the anchor ({@code null} not permitted). * @param orientation the orientation ({@code null} not permitted). * @param style the chart style ({@code null} not permitted). * * @return The legend. * * @since 1.2 */ @Override public TableElement createLegend(Plot3D plot, Anchor2D anchor, Orientation orientation, ChartStyle style) { TableElement legend = createSimpleLegend(plot.getLegendInfo(), anchor, orientation, style); if (this.header != null || this.footer != null) { GridElement compositeLegend = new GridElement<>(); compositeLegend.setBackground(null); if (header != null) { TextElement he = new TextElement(this.header, style.getLegendHeaderFont()); he.setHorizontalAligment(this.headerAlignment); he.setBackgroundColor(style.getLegendHeaderBackgroundColor()); compositeLegend.setElement(he, "R0", "C1"); } compositeLegend.setElement(legend, "R1", "C1"); if (this.footer != null) { TextElement fe = new TextElement(this.footer, style.getLegendFooterFont()); fe.setHorizontalAligment(this.footerAlignment); fe.setBackgroundColor(style.getLegendFooterBackgroundColor()); compositeLegend.setElement(fe, "R2", "C1"); } return compositeLegend; } else { return legend; } } /** * Creates a simple legend based on a flow layout of the individual legend * items. * * @param items the items to be added to the legend ({@code null} * not permitted). * @param anchor the anchor point ({@code null} not permitted). * @param orientation the orientation ({@code null} not permitted). * @param style the chart style. * * @return The simple legend. */ private TableElement createSimpleLegend(List items, Anchor2D anchor, Orientation orientation, ChartStyle style) { Args.nullNotPermitted(items, "items"); Args.nullNotPermitted(orientation, "orientation"); ContainerElement legend; if (orientation == Orientation.HORIZONTAL) { FlowElement fe = new FlowElement(horizontalAlignment(anchor), 2); fe.setRefPoint(anchor.getRefPt()); legend = fe; } else { VerticalFlowElement vfe = new VerticalFlowElement( verticalAlignment(anchor), 2); vfe.setRefPoint(anchor.getRefPt()); legend = vfe; } for (LegendItemInfo item : items) { Shape shape = item.getShape(); if (shape == null) { shape = style.getLegendItemShape(); } TableElement legendItem = createLegendItem(item.getLabel(), style.getLegendItemFont(), style.getLegendItemColor(), shape, item.getColor(), style.getLegendItemBackgroundColor()); legendItem.setProperty(TableElement.CLASS, InteractiveElementType.LEGEND_ITEM); legendItem.setProperty(Chart3D.SERIES_KEY, item.getSeriesKey()); legend.addElement(legendItem); } return legend; } /** * Returns the horizontal alignment that should be used. * * @param anchor the anchor ({@code null} not permitted). * * @return The horizontal alignment. */ private HAlign horizontalAlignment(Anchor2D anchor) { if (this.rowAlignment != null) { return this.rowAlignment; } if (anchor.getRefPt().isLeft()) { return HAlign.LEFT; } if (anchor.getRefPt().isRight()) { return HAlign.RIGHT; } return HAlign.CENTER; } /** * Returns the vertical alignment that should be used. * * @param anchor the anchor ({@code null} not permitted). * * @return The vertical alignment. */ private VAlign verticalAlignment(Anchor2D anchor) { if (this.columnAlignment != null) { return this.columnAlignment; } if (anchor.getRefPt().isTop()) { return VAlign.TOP; } if (anchor.getRefPt().isBottom()) { return VAlign.BOTTOM; } return VAlign.MIDDLE; } /** * Creates a single item in the legend (normally this represents one * data series from the dataset). * * @param text the legend item text ({@code null} not permitted). * @param font the font ({@code null} not permitted). * @param textColor the text color ({@code null} not permitted). * @param shape the shape ({@code null} not permitted). * @param shapeColor the shape color ({@code null} not permitted). * @param background the background color ({@code null} not * permitted). * * @return A legend item (never {@code null}). */ private TableElement createLegendItem(String text, Font font, Color textColor, Shape shape, Color shapeColor, Color background) { // defer argument checks... ShapeElement se = new ShapeElement(shape, shapeColor); se.setBackgroundColor(background); TextElement te = new TextElement(text, font); te.setColor(textColor); te.setBackgroundColor(background); GridElement ge = new GridElement<>(); ge.setElement(se, "R1", "C1"); ge.setElement(te, "R1", "C2"); return ge; } /** * Tests this legend builder for equality with an arbitrary object. * * @param obj the object ({@code null} permitted). * * @return A boolean. */ @Override public boolean equals(Object obj) { if (obj == this) { return true; } if (!(obj instanceof StandardLegendBuilder)) { return false; } StandardLegendBuilder that = (StandardLegendBuilder) obj; if (!ObjectUtils.equals(this.header, that.header)) { return false; } if (this.headerAlignment != that.headerAlignment) { return false; } if (!ObjectUtils.equals(this.footer, that.footer)) { return false; } if (this.footerAlignment != that.footerAlignment) { return false; } return true; } } orson-charts-2.1.0/src/main/java/org/jfree/chart3d/legend/StandardLegendItemInfo.java000066400000000000000000000111371417331271500304240ustar00rootroot00000000000000/* =========================================================== * Orson Charts : a 3D chart library for the Java(tm) platform * =========================================================== * * (C)opyright 2013-2022, by David Gilbert. All rights reserved. * * https://github.com/jfree/orson-charts * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . * * [Oracle and Java are registered trademarks of Oracle and/or its affiliates. * Other names may be trademarks of their respective owners.] * * If you do not wish to be bound by the terms of the GPL, an alternative * commercial license can be purchased. For details, please see visit the * Orson Charts home page: * * http://www.object-refinery.com/orsoncharts/index.html * */ package org.jfree.chart3d.legend; import java.awt.Shape; import java.util.HashMap; import java.util.Map; import java.awt.Color; import org.jfree.chart3d.internal.Args; /** * A standard implementation of the {@link LegendItemInfo} interface. */ public class StandardLegendItemInfo implements LegendItemInfo { /** The series key. */ private Comparable seriesKey; /** The series label. */ private String label; /** A description of the item. */ private String description; /** The color to represent this legend item. */ private Color color; /** The shape to represent this legend item. */ private Shape shape; /** Storage for other properties. */ private Map, Object> properties; /** * Creates a new instance. * * @param seriesKey the series key ({@code null} not permitted). * @param label the label ({@code null} not permitted). * @param color the color ({@code null} not permitted). */ public StandardLegendItemInfo(Comparable seriesKey, String label, Color color) { this(seriesKey, label, null, color, null); } /** * Creates a new instance with the specified attributes. * * @param seriesKey the series key ({@code null} not permitted). * @param label the label ({@code null} not permitted). * @param description the description ({@code null} permitted). * @param color the color ({@code null} not permitted). * @param shape the shape ({@code null} permitted). */ public StandardLegendItemInfo(Comparable seriesKey, String label, String description, Color color, Shape shape) { Args.nullNotPermitted(seriesKey, "seriesKey"); Args.nullNotPermitted(label, "label"); Args.nullNotPermitted(color, "color"); this.seriesKey = seriesKey; this.label = label; this.description = description; this.color = color; this.shape = shape; this.properties = new HashMap<>(); } /** * Returns the series key. * * @return The series key (never {@code null}). */ @Override public Comparable getSeriesKey() { return this.seriesKey; } /** * Returns the label for the legend item. * * @return The label (never {@code null}). */ @Override public String getLabel() { return this.label; } /** * Returns the description for the legend item. * * @return The description (possibly {@code null}). */ @Override public String getDescription() { return this.description; } /** * Returns the shape for the legend item. * * @return The shape (possibly {@code null}). */ @Override public Shape getShape() { return this.shape; } /** * Returns the color for the legend item. * * @return The color (never {@code null}). */ @Override public Color getColor() { return this.color; } /** * Returns the properties for the legend item. * * @return The properties for the legend item. */ @Override public Map, Object> getProperties() { return this.properties; } } orson-charts-2.1.0/src/main/java/org/jfree/chart3d/legend/package-info.java000066400000000000000000000001171417331271500264320ustar00rootroot00000000000000/** * Classes related to chart legends. */ package org.jfree.chart3d.legend; orson-charts-2.1.0/src/main/java/org/jfree/chart3d/marker/000077500000000000000000000000001417331271500232675ustar00rootroot00000000000000orson-charts-2.1.0/src/main/java/org/jfree/chart3d/marker/AbstractMarker.java000066400000000000000000000247121417331271500270450ustar00rootroot00000000000000/* =========================================================== * Orson Charts : a 3D chart library for the Java(tm) platform * =========================================================== * * (C)opyright 2013-2022, by David Gilbert. All rights reserved. * * https://github.com/jfree/orson-charts * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . * * [Oracle and Java are registered trademarks of Oracle and/or its affiliates. * Other names may be trademarks of their respective owners.] * * If you do not wish to be bound by the terms of the GPL, an alternative * commercial license can be purchased. For details, please see visit the * Orson Charts home page: * * http://www.object-refinery.com/orsoncharts/index.html * */ package org.jfree.chart3d.marker; import java.awt.FontMetrics; import java.awt.Graphics2D; import java.awt.geom.Line2D; import java.awt.geom.Rectangle2D; import javax.swing.event.EventListenerList; import org.jfree.chart3d.Chart3DChangeListener; import org.jfree.chart3d.ChartElementVisitor; import org.jfree.chart3d.graphics2d.Anchor2D; import org.jfree.chart3d.graphics2d.RefPt2D; import org.jfree.chart3d.graphics2d.TextAnchor; import org.jfree.chart3d.graphics3d.internal.Utils2D; import org.jfree.chart3d.internal.Args; import org.jfree.chart3d.internal.TextUtils; /** * A base class for implementing markers (includes the event notification * mechanism). * * @since 1.2 */ public abstract class AbstractMarker implements Marker { /** Storage for registered change listeners. */ private final transient EventListenerList listenerList; /** * Default constructor. */ AbstractMarker() { this.listenerList = new EventListenerList(); } /** * Draws a marker label. * * @param g2 the graphics target ({@code null} not permitted). * @param label the label. * @param x the x-coordinate for the anchor point. * @param y the y-cpordinate for the anchor point. * @param anchor the label anchor ({@code null} not permitted). * @param refLine a reference line that is used to determine the rotation * angle for the label ({@code null} not permitted). * @param reverse a flag to indicate reverse orientation. */ protected void drawMarkerLabel(Graphics2D g2, String label, double x, double y, Anchor2D anchor, Line2D refLine, boolean reverse) { double angle = Utils2D.calculateTheta(refLine); boolean vflip = false; if (angle > Math.PI / 2) { angle -= Math.PI; vflip = true; } if (angle < -Math.PI / 2) { angle += Math.PI; vflip = true; } if (reverse) { vflip = !vflip; } double lineLength = Utils2D.length(refLine); FontMetrics fm = g2.getFontMetrics(); Rectangle2D bounds = fm.getStringBounds(label, g2); if (bounds.getWidth() < lineLength) { TextAnchor textAnchor = deriveTextAnchorForLine(anchor.getRefPt(), !vflip); TextUtils.drawRotatedString(label, g2, (float) x, (float) y, textAnchor, angle, textAnchor); } } /** * Draws a marker label. * * @param g2 the graphics target ({@code null} not permitted). * @param label the label. * @param x the x-coordinate for the anchor point. * @param y the y-cpordinate for the anchor point. * @param anchor the label anchor ({@code null} not permitted). * @param refLine1 a reference line that is used to determine the rotation * angle for the label ({@code null} not permitted). * @param refLine2 a reference line that is used to determine the rotation * angle for the label ({@code null} not permitted). * @param reverse a flag to indicate reverse orientation. */ protected void drawMarkerLabel(Graphics2D g2, String label, double x, double y, Anchor2D anchor, Line2D refLine1, Line2D refLine2, boolean reverse) { double angle; if (anchor.getRefPt().isTop()) { angle = Utils2D.calculateTheta(refLine2); } else if (anchor.getRefPt().isBottom()) { angle = Utils2D.calculateTheta(refLine1); } else { angle = (Utils2D.calculateTheta(refLine1) + Utils2D.calculateTheta(refLine2)) / 2.0; } boolean vflip = false; if (angle > Math.PI / 2) { angle -= Math.PI; vflip = true; } if (angle < -Math.PI / 2) { angle += Math.PI; vflip = true; } if (reverse) { vflip = !vflip; } double lineLength1 = Utils2D.length(refLine1); double lineLength2 = Utils2D.length(refLine2); Rectangle2D bounds = g2.getFontMetrics().getStringBounds(label, g2); if (bounds.getWidth() < Math.min(lineLength1, lineLength2)) { TextAnchor textAnchor = deriveTextAnchor(anchor.getRefPt(), !vflip); TextUtils.drawRotatedString(label, g2, (float) x, (float) y, textAnchor, angle, textAnchor); } } /** * Receives a visitor. * * @param visitor the visitor. * * @since 1.2 */ @Override public void receive(ChartElementVisitor visitor) { visitor.visit(this); } /** * Registers a listener to receive notification of changes to the marker. * * @param listener the listener ({@code null} not permitted). */ @Override public void addChangeListener(MarkerChangeListener listener) { this.listenerList.add(MarkerChangeListener.class, listener); } /** * Deregisters a listener so that it no longer receives notification of * changes to the marker. * * @param listener the listener ({@code null} not permitted). */ @Override public void removeChangeListener(MarkerChangeListener listener) { this.listenerList.remove(MarkerChangeListener.class, listener); } /** * Sends a {@link MarkerChangeEvent} to all registered listeners. */ protected void fireChangeEvent() { Object[] listeners = this.listenerList.getListenerList(); for (int i = listeners.length - 2; i >= 0; i -= 2) { if (listeners[i] == Chart3DChangeListener.class) { ((MarkerChangeListener) listeners[i + 1]).markerChanged( new MarkerChangeEvent(this, this)); } } } /** * A utility method that returns a suitable text anchor for a given * reference point. This is used for range marker label positioning. * * @param refPt the reference point ({@code null} not permitted). * @param vflip is the text flipped vertically? * * @return A text anchor (never {@code null}). */ protected static TextAnchor deriveTextAnchor(RefPt2D refPt, boolean vflip) { Args.nullNotPermitted(refPt, "refPt"); if (refPt.equals(RefPt2D.TOP_LEFT)) { return vflip ? TextAnchor.TOP_LEFT : TextAnchor.BOTTOM_RIGHT; } else if (refPt.equals(RefPt2D.TOP_CENTER)) { return vflip ? TextAnchor.TOP_CENTER : TextAnchor.BOTTOM_CENTER; } else if (refPt.equals(RefPt2D.TOP_RIGHT)) { return vflip ? TextAnchor.TOP_RIGHT :TextAnchor.BOTTOM_LEFT; } if (refPt.equals(RefPt2D.CENTER_LEFT)) { return vflip ? TextAnchor.CENTER_LEFT : TextAnchor.CENTER_RIGHT; } else if (refPt.equals(RefPt2D.CENTER)) { return TextAnchor.CENTER; } else if (refPt.equals(RefPt2D.CENTER_RIGHT)) { return vflip ? TextAnchor.CENTER_RIGHT : TextAnchor.CENTER_LEFT; } else if (refPt.equals(RefPt2D.BOTTOM_LEFT)) { return vflip ? TextAnchor.BOTTOM_LEFT : TextAnchor.TOP_RIGHT; } else if (refPt.equals(RefPt2D.BOTTOM_CENTER)) { return vflip ? TextAnchor.BOTTOM_CENTER : TextAnchor.TOP_CENTER; } else if (refPt.equals(RefPt2D.BOTTOM_RIGHT)) { return vflip ? TextAnchor.BOTTOM_RIGHT : TextAnchor.TOP_LEFT; } throw new RuntimeException("Unknown refPt " + refPt); } /** * A utility method that returns a suitable text anchor for a given * reference point relative to a line (rather than a rectangle which is * the normal case). This is used for value marker label positioning. * * @param refPt the reference point ({@code null} not permitted). * @param vflip is the text flipped vertically? * * @return A text anchor (never {@code null}). */ protected static TextAnchor deriveTextAnchorForLine(RefPt2D refPt, boolean vflip) { if (refPt.equals(RefPt2D.TOP_LEFT)) { return vflip ? TextAnchor.BOTTOM_LEFT : TextAnchor.TOP_RIGHT; } else if (refPt.equals(RefPt2D.TOP_CENTER)) { return vflip ? TextAnchor.BOTTOM_CENTER : TextAnchor.TOP_CENTER; } else if (refPt.equals(RefPt2D.TOP_RIGHT)) { return vflip ? TextAnchor.BOTTOM_RIGHT :TextAnchor.TOP_LEFT; } if (refPt.equals(RefPt2D.CENTER_LEFT)) { return vflip ? TextAnchor.CENTER_LEFT : TextAnchor.CENTER_RIGHT; } else if (refPt.equals(RefPt2D.CENTER)) { return TextAnchor.CENTER; } else if (refPt.equals(RefPt2D.CENTER_RIGHT)) { return vflip ? TextAnchor.CENTER_RIGHT : TextAnchor.CENTER_LEFT; } else if (refPt.equals(RefPt2D.BOTTOM_LEFT)) { return vflip ? TextAnchor.TOP_LEFT : TextAnchor.BOTTOM_RIGHT; } else if (refPt.equals(RefPt2D.BOTTOM_CENTER)) { return vflip ? TextAnchor.TOP_CENTER : TextAnchor.BOTTOM_CENTER; } else if (refPt.equals(RefPt2D.BOTTOM_RIGHT)) { return vflip ? TextAnchor.TOP_RIGHT : TextAnchor.BOTTOM_LEFT; } throw new RuntimeException("Unknown refPt " + refPt); } } orson-charts-2.1.0/src/main/java/org/jfree/chart3d/marker/CategoryMarker.java000066400000000000000000000322571417331271500270620ustar00rootroot00000000000000/* =========================================================== * Orson Charts : a 3D chart library for the Java(tm) platform * =========================================================== * * (C)opyright 2013-2022, by David Gilbert. All rights reserved. * * https://github.com/jfree/orson-charts * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . * * [Oracle and Java are registered trademarks of Oracle and/or its affiliates. * Other names may be trademarks of their respective owners.] * * If you do not wish to be bound by the terms of the GPL, an alternative * commercial license can be purchased. For details, please see visit the * Orson Charts home page: * * http://www.object-refinery.com/orsoncharts/index.html * */ package org.jfree.chart3d.marker; import java.awt.Color; import java.awt.Font; import java.awt.Graphics2D; import java.awt.Stroke; import java.awt.geom.Line2D; import java.awt.geom.Path2D; import java.awt.geom.Point2D; import java.io.IOException; import java.io.ObjectInputStream; import java.io.ObjectOutputStream; import java.io.Serializable; import org.jfree.chart3d.axis.CategoryAxis3D; import org.jfree.chart3d.graphics2d.Anchor2D; import org.jfree.chart3d.internal.SerialUtils; import org.jfree.chart3d.internal.Args; import org.jfree.chart3d.internal.ObjectUtils; /** * A marker for a category on a {@link CategoryAxis3D}. This marker could be * used to highlight one selected category. *

* For an example, please refer to the demo {@code CategoryMarkerDemo1.java}. *

* NOTE: This class is serializable, but the serialization format is subject * to change in future releases and should not be relied upon for persisting * instances of this class. * * @since 1.2 */ @SuppressWarnings("serial") public class CategoryMarker extends AbstractMarker implements Serializable { /** The category to mark. */ Comparable category; /** * The marker type (used to indicate whether the marker is represented by * a line or a band). */ CategoryMarkerType type; /** The label for the marker (optional). */ private String label; /** The font for the label. */ private Font font; /** The color for the label. */ private Color labelColor; /** The anchor for the label. */ private Anchor2D labelAnchor; /** The stroke for the marker line(s). */ private transient Stroke lineStroke; /** The color for the marker line. */ private Color lineColor; /** The fill color used when drawing a band for the marker. */ private Color fillColor; /** * Creates a marker for the specified category. * * @param category the category key ({@code null} not permitted). */ public CategoryMarker(Comparable category) { super(); Args.nullNotPermitted(category, "category"); this.category = category; this.type = CategoryMarkerType.BAND; this.font = Marker.DEFAULT_MARKER_FONT; this.labelColor = Marker.DEFAULT_LABEL_COLOR; this.labelAnchor = Anchor2D.CENTER; this.lineStroke = DEFAULT_LINE_STROKE; this.lineColor = DEFAULT_LINE_COLOR; this.fillColor = DEFAULT_FILL_COLOR; } /** * Returns the category. * * @return The category (never {@code null}). */ public Comparable getCategory() { return this.category; } /** * Sets the category for the marker and sends a change event to all * registered listeners. * * @param category the new category ({@code null} not permitted). */ public void setCategory(Comparable category) { Args.nullNotPermitted(category, "category"); this.category = category; fireChangeEvent(); } /** * Returns the marker type which determines whether the marker is drawn * as a band (the default) or a line. * * @return The type (never {@code null}). */ public CategoryMarkerType getType() { return this.type; } /** * Sets the marker type and sends a change event to all registered * listeners. * * @param type the type ({@code null} not permitted). */ public void setType(CategoryMarkerType type) { Args.nullNotPermitted(type, "type"); this.type = type; fireChangeEvent(); } /** * Returns the label for the marker (if this is {@code null} then no * label is displayed). * * @return The label (possibly {@code null}). */ public String getLabel() { return this.label; } /** * Sets the label and sends a change event to all registered listeners. * * @param label the label ({@code null} permitted). */ public void setLabel(String label) { this.label = label; fireChangeEvent(); } /** * Returns the font for the label. The default value is * {@link Marker#DEFAULT_MARKER_FONT}. * * @return The font (never {@code null}). */ public Font getFont() { return this.font; } /** * Sets the font for the marker label and sends a change event to all * registered listeners. * * @param font the font ({@code null} not permitted). */ public void setFont(Font font) { Args.nullNotPermitted(font, "font"); this.font = font; fireChangeEvent(); } /** * Returns the label color. The default value is * {@link Marker#DEFAULT_LABEL_COLOR}. * * @return The label color (never {@code null}). */ public Color getLabelColor() { return this.labelColor; } /** * Sets the label color and sends a change event to all registered * listeners. * * @param color the color ({@code null} not permitted). */ public void setLabelColor(Color color) { Args.nullNotPermitted(color, "color"); this.labelColor = color; fireChangeEvent(); } /** * Returns the anchor for the label. The default value is * {@link Anchor2D#CENTER}. * * @return The anchor for the label. */ public Anchor2D getLabelAnchor() { return this.labelAnchor; } /** * Sets the anchor for the label and sends a change event to all registered * listeners. * * @param anchor the anchor ({@code null} not permitted). */ public void setLabelAnchor(Anchor2D anchor) { Args.nullNotPermitted(anchor, "anchor"); this.labelAnchor = anchor; fireChangeEvent(); } /** * Returns the line color for the marker. * * @return The line color (never {@code null}). */ public Color getLineColor() { return this.lineColor; } /** * Sets the line color for the marker and sends a change event to all * registered listeners. * * @param color the color ({@code null} not permitted). */ public void setLineColor(Color color) { Args.nullNotPermitted(color, "color"); this.lineColor = color; fireChangeEvent(); } /** * Returns the line stroke. The default value is * {@link Marker#DEFAULT_LINE_STROKE}. * * @return The line stroke (never {@code null}). */ public Stroke getLineStroke() { return this.lineStroke; } /** * Sets the line stroke and sends a change event to all registered * listeners. * * @param stroke the stroke ({@code null} not permitted). */ public void setLineStroke(Stroke stroke) { Args.nullNotPermitted(stroke, "stroke"); this.lineStroke = stroke; fireChangeEvent(); } /** * Returns the color used to fill the marker band. * * @return The color (never {@code null}). */ public Color getFillColor() { return this.fillColor; } /** * Sets the color used to fill the marker band and sends a change event * to all registered listeners. * * @param color the color ({@code null} not permitted). */ public void setFillColor(Color color) { Args.nullNotPermitted(color, "color"); this.fillColor = color; fireChangeEvent(); } /** * Handles drawing of the marker. This method is called by the library, * you won't normally call it directly. * * @param g2 the graphics device ({@code null} not permitted). * @param markerData the marker data ({@code null} not permitted). * @param reverse a flag to indicate reverse orientation. */ @Override public void draw(Graphics2D g2, MarkerData markerData, boolean reverse) { if (markerData.getType().equals(MarkerDataType.VALUE)) { MarkerLine ml = markerData.getValueLine(); g2.setPaint(this.lineColor); g2.setStroke(this.lineStroke); Line2D l = new Line2D.Double(ml.getStartPoint(), ml.getEndPoint()); g2.draw(l); Point2D labelPoint = markerData.getLabelPoint(); if (labelPoint != null) { g2.setFont(this.font); g2.setColor(this.labelColor); drawMarkerLabel(g2, this.label, labelPoint.getX(), labelPoint.getY(), this.labelAnchor, l, reverse); } } else if (markerData.getType().equals(MarkerDataType.RANGE)) { MarkerLine sl = markerData.getStartLine(); Line2D l1 = new Line2D.Double(sl.getStartPoint(), sl.getEndPoint()); MarkerLine el = markerData.getEndLine(); Line2D l2 = new Line2D.Double(el.getStartPoint(), el.getEndPoint()); Path2D path = new Path2D.Double(); path.moveTo(l1.getX1(), l1.getY1()); path.lineTo(l1.getX2(), l1.getY2()); path.lineTo(l2.getX2(), l2.getY2()); path.lineTo(l2.getX1(), l2.getY1()); path.closePath(); g2.setPaint(this.fillColor); g2.fill(path); g2.setColor(this.lineColor); g2.setStroke(this.lineStroke); g2.draw(l1); g2.draw(l2); Point2D labelPoint = markerData.getLabelPoint(); if (labelPoint != null) { g2.setFont(this.font); g2.setColor(this.labelColor); drawMarkerLabel(g2, this.label, labelPoint.getX(), labelPoint.getY(), markerData.getLabelAnchor(), l1, l2, reverse); } } } @Override public int hashCode() { int hash = 7; hash = 73 * hash + ObjectUtils.hashCode(this.category); return hash; } @Override public boolean equals(Object obj) { if (obj == null) { return false; } if (getClass() != obj.getClass()) { return false; } final CategoryMarker other = (CategoryMarker) obj; if (!ObjectUtils.equals(this.category, other.category)) { return false; } if (this.type != other.type) { return false; } if (!ObjectUtils.equals(this.label, other.label)) { return false; } if (!ObjectUtils.equals(this.font, other.font)) { return false; } if (!ObjectUtils.equals(this.labelColor, other.labelColor)) { return false; } if (!ObjectUtils.equals(this.labelAnchor, other.labelAnchor)) { return false; } if (!ObjectUtils.equals(this.lineStroke, other.lineStroke)) { return false; } if (!ObjectUtils.equals(this.lineColor, other.lineColor)) { return false; } if (!ObjectUtils.equals(this.fillColor, other.fillColor)) { return false; } return true; } /** * Provides serialization support. * * @param stream the output stream. * * @throws IOException if there is an I/O error. */ private void writeObject(ObjectOutputStream stream) throws IOException { stream.defaultWriteObject(); SerialUtils.writeStroke(this.lineStroke, stream); } /** * Provides serialization support. * * @param stream the input stream. * * @throws IOException if there is an I/O error. * @throws ClassNotFoundException if there is a classpath problem. */ private void readObject(ObjectInputStream stream) throws IOException, ClassNotFoundException { stream.defaultReadObject(); this.lineStroke = SerialUtils.readStroke(stream); } } orson-charts-2.1.0/src/main/java/org/jfree/chart3d/marker/CategoryMarkerType.java000066400000000000000000000032421417331271500277140ustar00rootroot00000000000000/* =========================================================== * Orson Charts : a 3D chart library for the Java(tm) platform * =========================================================== * * (C)opyright 2013-2022, by David Gilbert. All rights reserved. * * https://github.com/jfree/orson-charts * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . * * [Oracle and Java are registered trademarks of Oracle and/or its affiliates. * Other names may be trademarks of their respective owners.] * * If you do not wish to be bound by the terms of the GPL, an alternative * commercial license can be purchased. For details, please see visit the * Orson Charts home page: * * http://www.object-refinery.com/orsoncharts/index.html * */ package org.jfree.chart3d.marker; /** * An enumeration of the different types of {@link CategoryMarker}. * * @since 1.2 */ public enum CategoryMarkerType { /** The marker is represented as a line in the middle of the category. */ LINE, /** The marker is represented as a band covering the category width. */ BAND } orson-charts-2.1.0/src/main/java/org/jfree/chart3d/marker/Marker.java000066400000000000000000000062561417331271500253640ustar00rootroot00000000000000/* =========================================================== * Orson Charts : a 3D chart library for the Java(tm) platform * =========================================================== * * (C)opyright 2013-2022, by David Gilbert. All rights reserved. * * https://github.com/jfree/orson-charts * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . * * [Oracle and Java are registered trademarks of Oracle and/or its affiliates. * Other names may be trademarks of their respective owners.] * * If you do not wish to be bound by the terms of the GPL, an alternative * commercial license can be purchased. For details, please see visit the * Orson Charts home page: * * http://www.object-refinery.com/orsoncharts/index.html * */ package org.jfree.chart3d.marker; import java.awt.BasicStroke; import java.awt.Color; import java.awt.Font; import java.awt.Graphics2D; import java.awt.Stroke; import org.jfree.chart3d.ChartElement; /** * A base interface for all markers. * * @since 1.2 */ public interface Marker extends ChartElement { /** The default line stroke for markers. */ Stroke DEFAULT_LINE_STROKE = new BasicStroke(0f, BasicStroke.CAP_ROUND, BasicStroke.JOIN_ROUND); /** The default line color for markers. */ Color DEFAULT_LINE_COLOR = Color.DARK_GRAY; /** The default fill color for markers. */ Color DEFAULT_FILL_COLOR = new Color(128, 128, 192, 64); /** The default font for marker labels. */ Font DEFAULT_MARKER_FONT = new Font(Font.DIALOG, Font.PLAIN, 10); /** The default color for the marker labels. */ Color DEFAULT_LABEL_COLOR = Color.BLACK; /** * Draws the marker based on the {@code markerData} which has been * passed to the 3D engine to generate the required 2D projection points. * * @param g2 the graphics target ({@code null} not permitted). * @param markerData transient data for the marker ({@code null} not * permitted). * @param reverse a flag to indicate reverse orientation. */ void draw(Graphics2D g2, MarkerData markerData, boolean reverse); /** * Registers a listener to receive notification of changes to the marker. * * @param listener the listener ({@code null} not permitted). */ void addChangeListener(MarkerChangeListener listener); /** * Deregisters a listener so that it no longer receives notification of * changes to the marker. * * @param listener the listener ({@code null} not permitted). */ void removeChangeListener(MarkerChangeListener listener); } orson-charts-2.1.0/src/main/java/org/jfree/chart3d/marker/MarkerChangeEvent.java000066400000000000000000000054751417331271500274760ustar00rootroot00000000000000/* =========================================================== * Orson Charts : a 3D chart library for the Java(tm) platform * =========================================================== * * (C)opyright 2013-2022, by David Gilbert. All rights reserved. * * https://github.com/jfree/orson-charts * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . * * [Oracle and Java are registered trademarks of Oracle and/or its affiliates. * Other names may be trademarks of their respective owners.] * * If you do not wish to be bound by the terms of the GPL, an alternative * commercial license can be purchased. For details, please see visit the * Orson Charts home page: * * http://www.object-refinery.com/orsoncharts/index.html * */ package org.jfree.chart3d.marker; import java.util.EventObject; import org.jfree.chart3d.internal.Args; /** * An event associated with a change to a {@link Marker}. These change * events will be generated by an marker and broadcast to the axis that owns the * marker (in the standard setup, the axis will then trigger its own change e * vent to notify the plot that a subcomponent of the axis has changed). *

* NOTE: This class is serializable, but the serialization format is subject * to change in future releases and should not be relied upon for persisting * instances of this class. * * @since 1.2 */ @SuppressWarnings("serial") public class MarkerChangeEvent extends EventObject { /** The marker associated with this event. */ private Marker marker; /** * Creates a new event. * * @param marker the marker ({@code null} not permitted). */ public MarkerChangeEvent(Marker marker) { this(marker, marker); } /** * Creates a new event. * * @param source the event source. * @param marker the marker ({@code null} not permitted). */ public MarkerChangeEvent(Object source, Marker marker) { super(source); Args.nullNotPermitted(marker, "marker"); this.marker = marker; } /** * Returns the marker associated with this event. * * @return The marker (never {@code null}). */ public Marker getMarker() { return this.marker; } } orson-charts-2.1.0/src/main/java/org/jfree/chart3d/marker/MarkerChangeListener.java000066400000000000000000000033331417331271500301710ustar00rootroot00000000000000/* =========================================================== * Orson Charts : a 3D chart library for the Java(tm) platform * =========================================================== * * (C)opyright 2013-2022, by David Gilbert. All rights reserved. * * https://github.com/jfree/orson-charts * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . * * [Oracle and Java are registered trademarks of Oracle and/or its affiliates. * Other names may be trademarks of their respective owners.] * * If you do not wish to be bound by the terms of the GPL, an alternative * commercial license can be purchased. For details, please see visit the * Orson Charts home page: * * http://www.object-refinery.com/orsoncharts/index.html * */ package org.jfree.chart3d.marker; import java.util.EventListener; /** * A listener for marker change events. * * @since 1.2 */ public interface MarkerChangeListener extends EventListener { /** * Called to inform that an marker change event has occurred. * * @param event the event ({@code null} not permitted). */ void markerChanged(MarkerChangeEvent event); } orson-charts-2.1.0/src/main/java/org/jfree/chart3d/marker/MarkerData.java000066400000000000000000000224371417331271500261550ustar00rootroot00000000000000/* =========================================================== * Orson Charts : a 3D chart library for the Java(tm) platform * =========================================================== * * (C)opyright 2013-2022, by David Gilbert. All rights reserved. * * https://github.com/jfree/orson-charts * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . * * [Oracle and Java are registered trademarks of Oracle and/or its affiliates. * Other names may be trademarks of their respective owners.] * * If you do not wish to be bound by the terms of the GPL, an alternative * commercial license can be purchased. For details, please see visit the * Orson Charts home page: * * http://www.object-refinery.com/orsoncharts/index.html * */ package org.jfree.chart3d.marker; import java.awt.geom.Point2D; import java.util.Map; import java.util.HashMap; import org.jfree.chart3d.graphics2d.Anchor2D; import org.jfree.chart3d.internal.Args; /** * A record holder for data relating to markers that needs to be passed * to the 3D engine. * * @since 1.2 */ public class MarkerData { /** * The key used to store the marker on the axis. We can use this key * to retrieve the actual marker to get the label, font, color etc. */ private String markerKey; /** * The type of marker data (value or range). A value marker will have * a 'valueLine' stored in the data map. A range marker will have * a 'startLine' and an 'endLine' stored in the data map. */ private MarkerDataType type; /** Storage for data values (using a map for future expansion). */ private Map data; /** * Creates marker data for the case where there is a single line * (for example, the {@link NumberMarker} class). * * @param key the key for the marker ({@code null} not permitted). * @param pos the relative position along the axis (in the range 0.0 to * 1.0). */ public MarkerData(String key, double pos) { Args.nullNotPermitted(key, "key"); this.markerKey = key; this.type = MarkerDataType.VALUE; this.data = new HashMap<>(); this.data.put("valueLine", new MarkerLine(pos, false)); } /** * Creates marker data for the case where there are two lines. * (for example, the {@link RangeMarker} class). * * @param key the key ({@code null} not permitted). * @param startPos the relative start position. * @param startPegged is the start position pegged? * @param endPos the relative end position. * @param endPegged is the end position pegged? */ public MarkerData(String key, double startPos, boolean startPegged, double endPos, boolean endPegged) { Args.nullNotPermitted(key, "key"); this.markerKey = key; this.type = MarkerDataType.RANGE; this.data = new HashMap<>(); this.data.put("startLine", new MarkerLine(startPos, startPegged)); this.data.put("endLine", new MarkerLine(endPos, endPegged)); } /** * Creates a new instance based on an existing source that has type * {@code MarkerDataType.VALUE}. * * @param source the source ({@code null} not permitted). * @param v0 the vertex index for the start of the line. * @param v1 the vertex index for the end of the line. */ public MarkerData(MarkerData source, int v0, int v1) { Args.nullNotPermitted(source, "source"); if (!source.getType().equals(MarkerDataType.VALUE)) { throw new IllegalArgumentException("Must be MarkerDataType.VALUE"); } this.markerKey = source.markerKey; this.type = source.type; this.data = new HashMap<>(source.data); double pos = source.getValueLine().getPos(); MarkerLine valueLine = new MarkerLine(pos, false, v0, v1); this.data.put("valueLine", valueLine); } /** * Creates a new instance based on an existing source that has type * {@code MarkerDataType.Range}. * * @param source the source ({@code null} not permitted). * @param v0 the vertex index for the start of the first line. * @param v1 the vertex index for the end of the first line. * @param v2 the vertex index for the start of the second line. * @param v3 the vertex index for the end of the second line. */ public MarkerData(MarkerData source, int v0, int v1, int v2, int v3) { Args.nullNotPermitted(source, "source"); if (!source.getType().equals(MarkerDataType.RANGE)) { throw new IllegalArgumentException("Must be MarkerDataType.RANGE"); } this.markerKey = source.markerKey; this.type = MarkerDataType.RANGE; this.data = new HashMap<>(source.data); double startPos = source.getStartLine().getPos(); boolean startPegged = source.getStartLine().isPegged(); MarkerLine startLine = new MarkerLine(startPos, startPegged, v0, v1); this.data.put("startLine", startLine); double endPos = source.getEndLine().getPos(); boolean endPegged = source.getEndLine().isPegged(); MarkerLine endLine = new MarkerLine(endPos, endPegged, v2, v3); this.data.put("endLine", endLine); } /** * Returns the marker key (allows retrieval of the original marker object * when required). * * @return The marker key (never {@code null}). */ public String getMarkerKey() { return this.markerKey; } /** * Returns the type of marker data (value or range). * * @return The type (never {@code null}). */ public MarkerDataType getType() { return this.type; } /** * A convenience method that returns the value line data for a value marker. * * @return The value line (or {@code null}). */ public MarkerLine getValueLine() { return (MarkerLine) this.data.get("valueLine"); } /** * A convenience method that returns the start line data for a range marker. * * @return The start line (or {@code null}). */ public MarkerLine getStartLine() { return (MarkerLine) this.data.get("startLine"); } /** * A convenience method that returns the end line data for a range marker. * * @return The end line (or {@code null}). */ public MarkerLine getEndLine() { return (MarkerLine) this.data.get("endLine"); } /** * Returns the label anchor. * * @return The label anchor. */ public Anchor2D getLabelAnchor() { return (Anchor2D) this.data.get("labelAnchor"); } /** * Sets the label anchor. * * @param anchor the label anchor. */ public void setLabelAnchor(Anchor2D anchor) { this.data.put("labelAnchor", anchor); } /** * Returns the label vertex index. * * @return The label vertex index. */ public int getLabelVertexIndex() { Integer i = (Integer) this.data.get("labelVertexIndex"); return (i != null ? i : -1); } /** * Sets the label vertex index. * * @param labelVertexIndex the label vertex index. */ public void setLabelVertexIndex(int labelVertexIndex) { this.data.put("labelVertexIndex", labelVertexIndex); } /** * Returns the label projection point. * * @return The label projection point (possibly {@code null}). */ public Point2D getLabelPoint() { return (Point2D) this.data.get("labelPoint"); } /** * Updates the projected points for this marker. This needs to be done * before the markers can be drawn. * * @param pts the projected points for the world. */ public void updateProjection(Point2D[] pts) { if (this.type.equals(MarkerDataType.VALUE)) { MarkerLine line = getValueLine(); line.setStartPoint(pts[line.getV0()]); line.setEndPoint(pts[line.getV1()]); } else if (this.type.equals(MarkerDataType.RANGE)) { MarkerLine startLine = getStartLine(); startLine.setStartPoint(pts[startLine.getV0()]); startLine.setEndPoint(pts[startLine.getV1()]); MarkerLine endLine = getEndLine(); endLine.setStartPoint(pts[endLine.getV0()]); endLine.setEndPoint(pts[endLine.getV1()]); } int labelVertex = getLabelVertexIndex(); if (labelVertex >= 0) { this.data.put("labelPoint", pts[labelVertex]); } else { this.data.put("labelPoint", null); } } @Override public String toString() { return "MarkerData[key=" + this.markerKey + "]"; } } orson-charts-2.1.0/src/main/java/org/jfree/chart3d/marker/MarkerDataType.java000066400000000000000000000030671417331271500270150ustar00rootroot00000000000000/* =========================================================== * Orson Charts : a 3D chart library for the Java(tm) platform * =========================================================== * * (C)opyright 2013-2022, by David Gilbert. All rights reserved. * * https://github.com/jfree/orson-charts * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . * * [Oracle and Java are registered trademarks of Oracle and/or its affiliates. * Other names may be trademarks of their respective owners.] * * If you do not wish to be bound by the terms of the GPL, an alternative * commercial license can be purchased. For details, please see visit the * Orson Charts home page: * * http://www.object-refinery.com/orsoncharts/index.html * */ package org.jfree.chart3d.marker; /** * An enumeration of the different types of {@link MarkerData}. * * @since 1.2 */ public enum MarkerDataType { /** A single value. */ VALUE, /** A value range. */ RANGE } orson-charts-2.1.0/src/main/java/org/jfree/chart3d/marker/MarkerLine.java000066400000000000000000000123601417331271500261650ustar00rootroot00000000000000/* =========================================================== * Orson Charts : a 3D chart library for the Java(tm) platform * =========================================================== * * (C)opyright 2013-2022, by David Gilbert. All rights reserved. * * https://github.com/jfree/orson-charts * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . * * [Oracle and Java are registered trademarks of Oracle and/or its affiliates. * Other names may be trademarks of their respective owners.] * * If you do not wish to be bound by the terms of the GPL, an alternative * commercial license can be purchased. For details, please see visit the * Orson Charts home page: * * http://www.object-refinery.com/orsoncharts/index.html * */ package org.jfree.chart3d.marker; import java.awt.geom.Point2D; /** * A data object that represents a line within a {@link MarkerData} structure. * * @since 1.2 */ public class MarkerLine { /** The relative position along the axis (in the range 0.0 to 1.0). */ private double pos; /** * A flag indicating whether or not the line is pegged at the boundary of * the axis. If the line is pegged, then it is not drawn (since it lies * outside the visible range of the chart. */ private boolean pegged; /** The vertex index for the start of the line. */ private int v0; /** The vertex index for the end of the line. */ private int v1; /** The projected start point. */ private Point2D startPoint; /** The projected end point. */ private Point2D endPoint; /** * Creates a new marker line. * * @param pos the relative position (in the range 0.0 to 1.0). * @param pegged a flag indicating whether or not the line has been * pegged to the end of the range. */ public MarkerLine(double pos, boolean pegged) { this(pos, pegged, -1, -1); } /** * Creates a new marker line with vertex indices. * * @param pos the relative position (in the range 0.0 to 1.0). * @param pegged a flag indicating whether or not the line has been * pegged to the end of the range. * @param v0 the index of the first vertex. * @param v1 the index of the second vertex. */ public MarkerLine(double pos, boolean pegged, int v0, int v1) { this.pos = pos; this.pegged = pegged; this.v0 = v0; this.v1 = v1; this.startPoint = null; this.endPoint = null; } /** * Returns the relative position of the line along the axis. * * @return The relative position of the line along the axis. */ public double getPos() { return this.pos; } /** * Returns {@code true} if the line is pegged, and {@code false} * otherwise. This is used for range markers to indicate that the value * represented by the line falls outside the current axis range, so the * line has been moved to the nearest axis boundary ("pegged" to the axis * range). * * @return A boolean. */ public boolean isPegged() { return this.pegged; } /** * Returns the index of the vertex for the start of the line. * * @return The index. */ public int getV0() { return this.v0; } /** * Sets the index of the vertex for the start of the line. * * @param v0 the index. */ public void setV0(int v0) { this.v0 = v0; } /** * Returns the index of the vertex for the end of the line. * * @return The index. */ public int getV1() { return this.v1; } /** * Sets the index of the vertex for the end of the line. * * @param v1 the index. */ public void setV1(int v1) { this.v1 = v1; } /** * Returns the projected starting point for the line. * * @return The projected starting point (possibly {@code null}). */ Point2D getStartPoint() { return this.startPoint; } /** * Sets the projected starting point for the line. * * @param pt the projected point. */ public void setStartPoint(Point2D pt) { this.startPoint = pt; } /** * Returns the projected ending point for the line. * * @return The projected ending point (possibly {@code null}). */ Point2D getEndPoint() { return this.endPoint; } /** * Sets the projected ending point for the line. * * @param pt the projected point. */ public void setEndPoint(Point2D pt) { this.endPoint = pt; } } orson-charts-2.1.0/src/main/java/org/jfree/chart3d/marker/NumberMarker.java000066400000000000000000000247141417331271500265340ustar00rootroot00000000000000/* =========================================================== * Orson Charts : a 3D chart library for the Java(tm) platform * =========================================================== * * (C)opyright 2013-2022, by David Gilbert. All rights reserved. * * https://github.com/jfree/orson-charts * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . * * [Oracle and Java are registered trademarks of Oracle and/or its affiliates. * Other names may be trademarks of their respective owners.] * * If you do not wish to be bound by the terms of the GPL, an alternative * commercial license can be purchased. For details, please see visit the * Orson Charts home page: * * http://www.object-refinery.com/orsoncharts/index.html * */ package org.jfree.chart3d.marker; import java.awt.Color; import java.awt.Font; import java.awt.Graphics2D; import java.awt.Stroke; import java.awt.geom.Line2D; import java.awt.geom.Point2D; import java.io.IOException; import java.io.ObjectInputStream; import java.io.ObjectOutputStream; import java.io.Serializable; import org.jfree.chart3d.data.Range; import org.jfree.chart3d.graphics2d.Anchor2D; import org.jfree.chart3d.internal.Args; import org.jfree.chart3d.internal.ObjectUtils; import org.jfree.chart3d.internal.SerialUtils; /** * A marker used to mark one value on an axis. *

* NOTE: This class is serializable, but the serialization format is subject * to change in future releases and should not be relied upon for persisting * instances of this class. * * @since 1.2 */ @SuppressWarnings("serial") public class NumberMarker extends AbstractMarker implements ValueMarker, Serializable { /** The data value to be marked. */ private double value; /** The label for the marker (optional). */ private String label; /** The font for the label. */ private Font font; /** The color for the label. */ private Color labelColor; /** The anchor for the label. */ private Anchor2D labelAnchor; /** The stroke for the marker line. */ private transient Stroke stroke; /** The color for the marker line. */ private Color lineColor; /** * Creates a new marker. * * @param value the value. */ public NumberMarker(double value) { super(); this.value = value; this.label = null; this.font = DEFAULT_MARKER_FONT; this.labelColor = DEFAULT_LABEL_COLOR; this.stroke = DEFAULT_LINE_STROKE; this.lineColor = DEFAULT_LINE_COLOR; this.labelAnchor = Anchor2D.CENTER; } /** * Returns the value for the marker (the initial value comes from the * constructor). * * @return The value. */ public double getValue() { return this.value; } /** * Sets the value for the marker and sends a change event to all registered * listeners. * * @param value the value. */ public void setValue(double value) { this.value = value; fireChangeEvent(); } /** * Returns the range for the marker (in this case, a single value range). * This method is used by the axis to filter out markers that do not touch * the current axis range. * * @return The range for the marker (never {@code null}). */ @Override public Range getRange() { return new Range(this.value, this.value); } /** * Returns the label for the marker (if this is {@code null} then no * label is displayed). The default value is {@code null}. * * @return The label (possibly {@code null}). */ public String getLabel() { return this.label; } /** * Sets the label and sends a change event to all registered listeners. * * @param label the label ({@code null} permitted). */ public void setLabel(String label) { this.label = label; fireChangeEvent(); } /** * Returns the font for the label. The default value is * {@link Marker#DEFAULT_MARKER_FONT}. * * @return The font (never {@code null}). */ public Font getFont() { return this.font; } /** * Sets the font for the marker label and sends a change event to all * registered listeners. * * @param font the font ({@code null} not permitted). */ public void setFont(Font font) { Args.nullNotPermitted(font, "font"); this.font = font; fireChangeEvent(); } /** * Returns the label color. The default value is * {@link Marker#DEFAULT_LABEL_COLOR}. * * @return The label color (never {@code null}). */ public Color getLabelColor() { return this.labelColor; } /** * Sets the label color and sends a change event to all registered * listeners. * * @param color the color ({@code null} not permitted). */ public void setLabelColor(Color color) { Args.nullNotPermitted(color, "color"); this.labelColor = color; fireChangeEvent(); } /** * Returns the anchor for the label. The default value is * {@link Anchor2D#CENTER}. * * @return The anchor for the label. */ public Anchor2D getLabelAnchor() { return this.labelAnchor; } /** * Sets the anchor for the label and sends a change event to all registered * listeners. * * @param anchor the anchor ({@code null} not permitted). */ public void setLabelAnchor(Anchor2D anchor) { Args.nullNotPermitted(anchor, "anchor"); this.labelAnchor = anchor; fireChangeEvent(); } /** * Returns the stroke for the marker line. The default value is * {@link Marker#DEFAULT_LINE_STROKE}. * * @return The stroke for the marker line (never {@code null}). */ public Stroke getLineStroke() { return this.stroke; } /** * Sets the stroke for the marker line and sends a change event to all * registered listeners. * * @param stroke the stroke ({@code null} not permitted). */ public void setLineStroke(Stroke stroke) { Args.nullNotPermitted(stroke, "stroke"); this.stroke = stroke; fireChangeEvent(); } /** * Returns the color for the marker line. The default value is * {@link Marker#DEFAULT_LINE_COLOR}. * * @return The color for the marker line (never {@code null}). */ public Color getLineColor() { return this.lineColor; } /** * Sets the color for the marker line and sends a change event to all * registered listeners. * * @param color the color ({@code null} not permitted). */ public void setLineColor(Color color) { Args.nullNotPermitted(color, "color"); this.lineColor = color; fireChangeEvent(); } /** * Draws the marker. This method is called by the library, you won't * normally call it directly. * * @param g2 the graphics target ({@code null} not permitted). * @param markerData transient marker data ({@code null} not * permitted). */ @Override public void draw(Graphics2D g2, MarkerData markerData, boolean reverse) { MarkerLine line = markerData.getValueLine(); g2.setPaint(this.lineColor); g2.setStroke(this.stroke); Line2D l = new Line2D.Double(line.getStartPoint(), line.getEndPoint()); g2.draw(l); Point2D labelPoint = markerData.getLabelPoint(); if (labelPoint != null) { g2.setFont(this.font); g2.setColor(this.labelColor); drawMarkerLabel(g2, this.label, labelPoint.getX(), labelPoint.getY(), this.labelAnchor, l, reverse); } } @Override public int hashCode() { int hash = 7; hash = 19 * hash + (int) (Double.doubleToLongBits(this.value) ^ (Double.doubleToLongBits(this.value) >>> 32)); hash = 19 * hash + ObjectUtils.hashCode(this.label); return hash; } @Override public boolean equals(Object obj) { if (obj == null) { return false; } if (getClass() != obj.getClass()) { return false; } final NumberMarker other = (NumberMarker) obj; if (Double.doubleToLongBits(this.value) != Double.doubleToLongBits(other.value)) { return false; } if (!ObjectUtils.equals(this.label, other.label)) { return false; } if (!ObjectUtils.equals(this.font, other.font)) { return false; } if (!ObjectUtils.equals(this.labelColor, other.labelColor)) { return false; } if (!ObjectUtils.equals(this.labelAnchor, other.labelAnchor)) { return false; } if (!ObjectUtils.equals(this.stroke, other.stroke)) { return false; } if (!ObjectUtils.equals(this.lineColor, other.lineColor)) { return false; } return true; } /** * Provides serialization support. * * @param stream the output stream. * * @throws IOException if there is an I/O error. */ private void writeObject(ObjectOutputStream stream) throws IOException { stream.defaultWriteObject(); SerialUtils.writeStroke(this.stroke, stream); } /** * Provides serialization support. * * @param stream the input stream. * * @throws IOException if there is an I/O error. * @throws ClassNotFoundException if there is a classpath problem. */ private void readObject(ObjectInputStream stream) throws IOException, ClassNotFoundException { stream.defaultReadObject(); this.stroke = SerialUtils.readStroke(stream); } } orson-charts-2.1.0/src/main/java/org/jfree/chart3d/marker/RangeMarker.java000066400000000000000000000246261417331271500263420ustar00rootroot00000000000000/* =========================================================== * Orson Charts : a 3D chart library for the Java(tm) platform * =========================================================== * * (C)opyright 2013-2022, by David Gilbert. All rights reserved. * * https://github.com/jfree/orson-charts * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . * * [Oracle and Java are registered trademarks of Oracle and/or its affiliates. * Other names may be trademarks of their respective owners.] * * If you do not wish to be bound by the terms of the GPL, an alternative * commercial license can be purchased. For details, please see visit the * Orson Charts home page: * * http://www.object-refinery.com/orsoncharts/index.html * */ package org.jfree.chart3d.marker; import java.awt.Color; import java.awt.Font; import java.awt.Graphics2D; import java.awt.geom.Line2D; import java.awt.geom.Path2D; import java.awt.geom.Point2D; import java.io.Serializable; import org.jfree.chart3d.data.Range; import org.jfree.chart3d.graphics2d.Anchor2D; import org.jfree.chart3d.internal.Args; import org.jfree.chart3d.internal.ObjectUtils; /** * A marker that marks a range of values on an axis. *

* For an example, please refer to the demo {@code RangeMarkerDemo1.java}. *

* NOTE: This class is serializable, but the serialization format is subject * to change in future releases and should not be relied upon for persisting * instances of this class. * * @since 1.2 */ @SuppressWarnings("serial") public class RangeMarker extends AbstractMarker implements ValueMarker, MarkerChangeListener, Serializable { /** The start of the range. */ private NumberMarker start; /** The end of the range. */ private NumberMarker end; /** The label for the marker (optional). */ private String label; /** The font for the label. */ private Font font; /** The color for the label. */ private Color labelColor; /** The anchor for the label. */ private Anchor2D labelAnchor; /** The color used to fill the band representing the marker range. */ Color fillColor; /** * Creates a new range marker for the given bounds. * * @param lowerBound the lower bound. * @param upperBound the upper bound. */ public RangeMarker(double lowerBound, double upperBound) { this(lowerBound, upperBound, null); } /** * Creates a new range marker for the given bounds. * * @param lowerBound the lower bound. * @param upperBound the upper bound. * @param label the label ({@code null} permitted). */ public RangeMarker(double lowerBound, double upperBound, String label) { super(); this.start = new NumberMarker(lowerBound); this.start.addChangeListener(this); this.end = new NumberMarker(upperBound); this.end.addChangeListener(this); this.label = label; this.font = DEFAULT_MARKER_FONT; this.labelColor = DEFAULT_LABEL_COLOR; this.labelAnchor = Anchor2D.CENTER; this.fillColor = DEFAULT_FILL_COLOR; } /** * Returns the starting point for the range marker. * * @return The starting point. */ public NumberMarker getStart() { return this.start; } /** * Returns the ending point for the range marker. * * @return The ending point. */ public NumberMarker getEnd() { return this.end; } /** * Returns the range of values for the marker. * * @return The range of values for the marker. */ @Override public Range getRange() { return new Range(this.start.getValue(), this.end.getValue()); } /** * Returns the label for the marker (if this is {@code null} then no * label is displayed). * * @return The label (possibly {@code null}). */ public String getLabel() { return this.label; } /** * Sets the label and sends a change event to all registered listeners. If * the label is set to {@code null} then no label is displayed for * the marker. * * @param label the label ({@code null} permitted). */ public void setLabel(String label) { this.label = label; fireChangeEvent(); } /** * Returns the font for the label. The default value is * {@link Marker#DEFAULT_MARKER_FONT}. * * @return The font (never {@code null}). */ public Font getFont() { return this.font; } /** * Sets the font for the marker label and sends a change event to all * registered listeners. * * @param font the font ({@code null} not permitted). */ public void setFont(Font font) { Args.nullNotPermitted(font, "font"); this.font = font; fireChangeEvent(); } /** * Returns the label color. The default value is * {@link Marker#DEFAULT_LABEL_COLOR}. * * @return The label color (never {@code null}). */ public Color getLabelColor() { return this.labelColor; } /** * Sets the label color and sends a change event to all registered * listeners. * * @param color the color ({@code null} not permitted). */ public void setLabelColor(Color color) { Args.nullNotPermitted(color, "color"); this.labelColor = color; fireChangeEvent(); } /** * Returns the anchor for the label. The default value is * {@link Anchor2D#CENTER}. * * @return The anchor for the label. */ public Anchor2D getLabelAnchor() { return this.labelAnchor; } /** * Sets the anchor for the label and sends a change event to all registered * listeners. * * @param anchor the anchor ({@code null} not permitted). */ public void setLabelAnchor(Anchor2D anchor) { Args.nullNotPermitted(anchor, "anchor"); this.labelAnchor = anchor; fireChangeEvent(); } /** * Returns the color used to fill the band representing the range for * the marker. The default value is {@link Marker#DEFAULT_FILL_COLOR}. * * @return The fill color (never {@code null}). */ public Color getFillColor() { return this.fillColor; } /** * Sets the color used to fill the band representing the range for the * marker and sends a change event to all registered listeners. * * @param color the color ({@code null} not permitted). */ public void setFillColor(Color color) { Args.nullNotPermitted(color, "color"); this.fillColor = color; fireChangeEvent(); } @Override public void draw(Graphics2D g2, MarkerData markerData, boolean reverse) { MarkerLine startLine = markerData.getStartLine(); Line2D l1 = new Line2D.Double(startLine.getStartPoint(), startLine.getEndPoint()); MarkerLine endLine = markerData.getEndLine(); Line2D l2 = new Line2D.Double(endLine.getStartPoint(), endLine.getEndPoint()); Path2D path = new Path2D.Double(); path.moveTo(l1.getX1(), l1.getY1()); path.lineTo(l1.getX2(), l1.getY2()); path.lineTo(l2.getX2(), l2.getY2()); path.lineTo(l2.getX1(), l2.getY1()); path.closePath(); g2.setPaint(this.fillColor); g2.fill(path); if (!startLine.isPegged()) { g2.setPaint(this.start.getLineColor()); g2.setStroke(this.start.getLineStroke()); g2.draw(l1); } if (!endLine.isPegged()) { g2.setPaint(this.end.getLineColor()); g2.setStroke(this.end.getLineStroke()); g2.draw(l2); } Point2D labelPoint = markerData.getLabelPoint(); if (labelPoint != null) { g2.setFont(this.font); g2.setColor(this.labelColor); drawMarkerLabel(g2, this.label, labelPoint.getX(), labelPoint.getY(), markerData.getLabelAnchor(), l1, l2, reverse); } } /** * Receives notification of a change to the start or end marker for the * range. * * @param event the event ({@code null} not permitted). */ @Override public void markerChanged(MarkerChangeEvent event) { fireChangeEvent(); } @Override public int hashCode() { int hash = 7; hash = 97 * hash + ObjectUtils.hashCode(this.start); hash = 97 * hash + ObjectUtils.hashCode(this.end); hash = 97 * hash + ObjectUtils.hashCode(this.label); return hash; } /** * Tests this marker for equality with an arbitrary object. * * @param obj the object to test against ({@code null} permitted). * * @return A boolean. */ @Override public boolean equals(Object obj) { if (obj == null) { return false; } if (getClass() != obj.getClass()) { return false; } final RangeMarker other = (RangeMarker) obj; if (!ObjectUtils.equals(this.start, other.start)) { return false; } if (!ObjectUtils.equals(this.end, other.end)) { return false; } if (!ObjectUtils.equals(this.label, other.label)) { return false; } if (!ObjectUtils.equals(this.font, other.font)) { return false; } if (!ObjectUtils.equals(this.labelColor, other.labelColor)) { return false; } if (!ObjectUtils.equals(this.labelAnchor, other.labelAnchor)) { return false; } if (!ObjectUtils.equals(this.fillColor, other.fillColor)) { return false; } return true; } } orson-charts-2.1.0/src/main/java/org/jfree/chart3d/marker/ValueMarker.java000066400000000000000000000035711417331271500263560ustar00rootroot00000000000000/* =========================================================== * Orson Charts : a 3D chart library for the Java(tm) platform * =========================================================== * * (C)opyright 2013-2022, by David Gilbert. All rights reserved. * * https://github.com/jfree/orson-charts * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . * * [Oracle and Java are registered trademarks of Oracle and/or its affiliates. * Other names may be trademarks of their respective owners.] * * If you do not wish to be bound by the terms of the GPL, an alternative * commercial license can be purchased. For details, please see visit the * Orson Charts home page: * * http://www.object-refinery.com/orsoncharts/index.html * */ package org.jfree.chart3d.marker; import org.jfree.chart3d.data.Range; /** * A marker that can be used to mark a value or range of values on a * {@link org.jfree.chart3d.axis.ValueAxis3D}. * * @since 1.2 */ public interface ValueMarker extends Marker { /** * Returns the range of values covered by the marker. If the marker * represents a single value rather than a range of values, then the range * that is returned will have zero length. * * @return The range (never {@code null}). */ Range getRange(); } orson-charts-2.1.0/src/main/java/org/jfree/chart3d/marker/package-info.java000066400000000000000000000002001417331271500264460ustar00rootroot00000000000000/** * Provides value and range marker support for the axes on category and XYZ * plots. */ package org.jfree.chart3d.marker;orson-charts-2.1.0/src/main/java/org/jfree/chart3d/package-info.java000066400000000000000000000002751417331271500252010ustar00rootroot00000000000000/** * Core classes, including {@link org.jfree.chart3d.Chart3D}, * {@link org.jfree.chart3d.Chart3DPanel} and * {@link org.jfree.chart3d.Chart3DFactory}. */ package org.jfree.chart3d; orson-charts-2.1.0/src/main/java/org/jfree/chart3d/plot/000077500000000000000000000000001417331271500227645ustar00rootroot00000000000000orson-charts-2.1.0/src/main/java/org/jfree/chart3d/plot/AbstractPlot3D.java000066400000000000000000000232671417331271500264320ustar00rootroot00000000000000/* =========================================================== * Orson Charts : a 3D chart library for the Java(tm) platform * =========================================================== * * (C)opyright 2013-2022, by David Gilbert. All rights reserved. * * https://github.com/jfree/orson-charts * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . * * [Oracle and Java are registered trademarks of Oracle and/or its affiliates. * Other names may be trademarks of their respective owners.] * * If you do not wish to be bound by the terms of the GPL, an alternative * commercial license can be purchased. For details, please see visit the * Orson Charts home page: * * http://www.object-refinery.com/orsoncharts/index.html * */ package org.jfree.chart3d.plot; import java.io.IOException; import java.io.ObjectInputStream; import java.io.Serializable; import javax.swing.event.EventListenerList; import org.jfree.chart3d.Chart3D; import org.jfree.chart3d.ChartElementVisitor; import org.jfree.chart3d.data.Dataset3DChangeEvent; import org.jfree.chart3d.data.Dataset3DChangeListener; import org.jfree.chart3d.data.ItemKey; import org.jfree.chart3d.graphics3d.Dimension3D; /** * A base class that can be used to create classes that implement * {@link Plot3D}. *

* A mechanism is provided for registering change listeners * on the plot. Whenever some attribute of the plot changes, all the * registered listeners are notified. The {@link Chart3D} instance that owns * the plot will be automatically registered as a listener so that it receives * notification whenever the plot (or some other object managed by the plot) * changes. *

* Typically a plot registers itself as a change listener on its dataset * and whenever a dataset change notification is received, the plot will * pass on a {@link Plot3DChangeEvent} to all *its* listeners. If the plot * has axes, then the same approach is used to listen for changes to the axes. *

* NOTE: This class is serializable, but the serialization format is subject * to change in future releases and should not be relied upon for persisting * instances of this class. */ @SuppressWarnings("serial") public abstract class AbstractPlot3D implements Plot3D, Dataset3DChangeListener, Serializable { /** The chart that this plot is assigned to, if any. */ private Chart3D chart; /** * The plot dimensions in 3D space. By default, this is auto-adjusted * according to the dataset, but the user can override this. */ protected Dimension3D dimensions; /** * A flag that controls whether or not the plot dimensions (in the 3D * model) are adjusted automatically. */ protected boolean autoAdjustDimensions; /** Storage for registered change listeners. */ private transient EventListenerList listenerList; /** * A flag that controls whether or not the plot will notify listeners * of changes (defaults to {@code true}, but sometimes it is useful * to disable this). */ private boolean notify; /** * Default constructor. */ protected AbstractPlot3D() { this.chart = null; this.dimensions = new Dimension3D(1.0, 1.0, 1.0); this.autoAdjustDimensions = true; this.listenerList = new EventListenerList(); this.notify = true; } /** * Returns the chart that the plot is assigned to, if any. * * @return The chart (possibly {@code null}). * * @since 1.2 */ @Override public Chart3D getChart() { return this.chart; } /** * Sets the chart that the plot is assigned to. * * @param chart the chart ({@code null} permitted). * * @since 1.2 */ @Override public void setChart(Chart3D chart) { this.chart = chart; } /** * Returns the dimensions of the box in 3D space into which the plot will * be composed. The dimension can change according to the shape of the * data. * * @return The dimensions of the plot (never {@code null}). * * @see #isAutoAdjustDimensions() */ @Override public Dimension3D getDimensions() { return this.dimensions; } /** * Returns the flag that controls whether or not the plot dimensions are * auto-adjusted when the dataset changes. Certain subclasses will allow * this flag to be changed ({@link CategoryPlot3D} and {@link XYZPlot}) * while others will always auto-adjust the dimensions ({@link PiePlot3D}). * * @return A boolean. */ public boolean isAutoAdjustDimensions() { return this.autoAdjustDimensions; } /** * Returns the tool tip text for the specified data item, or * {@code null} if no tool tip is required. * * @param itemKey the item key ({@code null} not permitted). * * @return The tool tip text (possibly {@code null}). * * @since 1.3 */ @Override public abstract String generateToolTipText(ItemKey itemKey); /** * Accepts a {@link ChartElementVisitor}. This is part of * a general purpose mechanism for traversing the chart * structure, you won't normally call this method directly. * * @param visitor the visitor (never {@code null}). */ @Override public abstract void receive(ChartElementVisitor visitor); /** * Tests this plot for equality with an arbitrary object. * * @param obj the object ({@code null} permitted). * * @return A boolean. */ @Override public boolean equals(Object obj) { if (obj == this) { return true; } if (!(obj instanceof AbstractPlot3D)) { return false; } AbstractPlot3D that = (AbstractPlot3D) obj; if (!this.dimensions.equals(that.dimensions)) { return false; } return true; } /** * Returns a flag that controls whether or not change events are sent to * registered listeners. * * @return A boolean. * * @see #setNotify(boolean) */ public boolean isNotify() { return this.notify; } /** * Sets a flag that controls whether or not listeners receive * {@link Plot3DChangeEvent} notifications. * * @param notify a boolean. * * @see #isNotify() */ public void setNotify(boolean notify) { this.notify = notify; // if the flag is being set to true, there may be queued up changes... if (notify) { fireChangeEvent(true); } } /** * Registers an object for notification of changes to the plot. * * @param listener the object to be registered. * * @see #removeChangeListener(Plot3DChangeListener) */ @Override public void addChangeListener(Plot3DChangeListener listener) { this.listenerList.add(Plot3DChangeListener.class, listener); } /** * Unregisters an object for notification of changes to the plot. * * @param listener the object to be unregistered. * * @see #addChangeListener(Plot3DChangeListener) */ @Override public void removeChangeListener(Plot3DChangeListener listener) { this.listenerList.remove(Plot3DChangeListener.class, listener); } /** * Notifies all registered listeners that the plot has been modified. * * @param event information about the change event. */ public void notifyListeners(Plot3DChangeEvent event) { // if the 'notify' flag has been switched to false, we don't notify // the listeners if (!this.notify) { return; } Object[] listeners = this.listenerList.getListenerList(); for (int i = listeners.length - 2; i >= 0; i -= 2) { if (listeners[i] == Plot3DChangeListener.class) { ((Plot3DChangeListener) listeners[i + 1]).plotChanged(event); } } } /** * Sends a {@link Plot3DChangeEvent} to all registered listeners. * * @param requiresWorldUpdate requires the world to be updated? */ protected void fireChangeEvent(boolean requiresWorldUpdate) { notifyListeners(new Plot3DChangeEvent(this, this, requiresWorldUpdate)); } /** * Receives notification of a dataset change, and passes this event on * wrapped in a {@link Plot3DChangeEvent}. * * @param event the dataset change event. */ @Override public void datasetChanged(Dataset3DChangeEvent event) { notifyListeners(new Plot3DChangeEvent(event, this, true)); } /** * Provides serialization support. * * @param stream the input stream. * * @throws IOException if there is an I/O error. * @throws ClassNotFoundException if there is a classpath problem. */ private void readObject(ObjectInputStream stream) throws IOException, ClassNotFoundException { stream.defaultReadObject(); // recreate an empty listener list this.listenerList = new EventListenerList(); } } orson-charts-2.1.0/src/main/java/org/jfree/chart3d/plot/CategoryPlot3D.java000066400000000000000000000757721417331271500264540ustar00rootroot00000000000000/* =========================================================== * Orson Charts : a 3D chart library for the Java(tm) platform * =========================================================== * * (C)opyright 2013-2022, by David Gilbert. All rights reserved. * * https://github.com/jfree/orson-charts * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . * * [Oracle and Java are registered trademarks of Oracle and/or its affiliates. * Other names may be trademarks of their respective owners.] * * If you do not wish to be bound by the terms of the GPL, an alternative * commercial license can be purchased. For details, please see visit the * Orson Charts home page: * * http://www.object-refinery.com/orsoncharts/index.html * */ package org.jfree.chart3d.plot; import java.awt.BasicStroke; import java.awt.Color; import java.awt.Paint; import java.awt.Stroke; import java.io.IOException; import java.io.ObjectInputStream; import java.io.ObjectOutputStream; import java.io.Serializable; import java.util.ArrayList; import java.util.List; import org.jfree.chart3d.Chart3D; import org.jfree.chart3d.ChartElementVisitor; import org.jfree.chart3d.axis.Axis3DChangeEvent; import org.jfree.chart3d.axis.Axis3DChangeListener; import org.jfree.chart3d.axis.CategoryAxis3D; import org.jfree.chart3d.axis.ValueAxis3D; import org.jfree.chart3d.data.Dataset3DChangeEvent; import org.jfree.chart3d.data.ItemKey; import org.jfree.chart3d.data.KeyedValues3DItemKey; import org.jfree.chart3d.data.category.CategoryDataset3D; import org.jfree.chart3d.graphics3d.Dimension3D; import org.jfree.chart3d.graphics3d.World; import org.jfree.chart3d.internal.Args; import org.jfree.chart3d.internal.ObjectUtils; import org.jfree.chart3d.internal.SerialUtils; import org.jfree.chart3d.label.CategoryItemLabelGenerator; import org.jfree.chart3d.label.CategoryLabelGenerator; import org.jfree.chart3d.label.StandardCategoryItemLabelGenerator; import org.jfree.chart3d.label.StandardCategoryLabelGenerator; import org.jfree.chart3d.legend.LegendItemInfo; import org.jfree.chart3d.legend.StandardLegendItemInfo; import org.jfree.chart3d.renderer.Renderer3DChangeEvent; import org.jfree.chart3d.renderer.Renderer3DChangeListener; import org.jfree.chart3d.renderer.category.CategoryRenderer3D; /** * A 3D plot with two category axes (x and z) and a numerical y-axis that can * display data from a {@link CategoryDataset3D}. *

* The plot implements several listener interfaces so that it can receive * notification of changes to its dataset, axes and renderer. When change events * are received, the plot passes on a {@link Plot3DChangeEvent} to the * {@link Chart3D} instance that owns the plot. This event chain is the * mechanism that ensures that charts are repainted whenever the dataset * changes, or when changes are made to the configuration of any chart * component. *

* NOTE: This class is serializable, but the serialization format is subject to * change in future releases and should not be relied upon for persisting * instances of this class. */ @SuppressWarnings("serial") public class CategoryPlot3D extends AbstractPlot3D implements Axis3DChangeListener, Renderer3DChangeListener, Serializable { private static final Stroke DEFAULT_GRIDLINE_STROKE = new BasicStroke(0.5f, BasicStroke.CAP_ROUND, BasicStroke.JOIN_ROUND, 1f, new float[]{3f, 3f}, 0f); /** * The dataset. */ private CategoryDataset3D dataset; /** * The renderer (never {@code null}). */ private CategoryRenderer3D renderer; /** * The row axis. */ private CategoryAxis3D rowAxis; /** * The column axis. */ private CategoryAxis3D columnAxis; /** * The value axis. */ private ValueAxis3D valueAxis; /** * Are gridlines shown for the row (z) axis? */ private boolean gridlinesVisibleForRows; /** * The paint for the row axis gridlines (never {@code null}). */ private transient Paint gridlinePaintForRows; /** * The stroke for the row axis gridlines (never {@code null}). */ private transient Stroke gridlineStrokeForRows; /** * Are gridlines shown for the column (x) axis? */ private boolean gridlinesVisibleForColumns; /** * The paint for the column axis gridlines (never {@code null}). */ private transient Paint gridlinePaintForColumns; /** * The stroke for the column axis gridlines (never {@code null}). */ private transient Stroke gridlineStrokeForColumns; /** * Are gridlines shown for the value axis? */ private boolean gridlinesVisibleForValues; /** * The paint for the value axis gridlines (never {@code null}). */ private transient Paint gridlinePaintForValues; /** * The stroke for the value axis gridlines (never {@code null}). */ private transient Stroke gridlineStrokeForValues; /** * The legend label generator. */ private CategoryLabelGenerator legendLabelGenerator; /** * A special attribute to provide control over the y-dimension for the plot * when the plot dimensions are auto-calculated. The default value is * {@code null}. * * @since 1.2 */ private Double yDimensionOverride; /** * The tool tip generator (if null there will be no tool tips). * * @since 1.3 */ private CategoryItemLabelGenerator toolTipGenerator; /** * Creates a new plot with the supplied dataset, renderer and axes. * * @param dataset the dataset ({@code null} not permitted). * @param renderer the renderer ({@code null} not permitted). * @param rowAxis the row axis ({@code null} not permitted). * @param columnAxis the column axis ({@code null} not permitted). * @param valueAxis the value axis ({@code null} not permitted). */ public CategoryPlot3D(CategoryDataset3D dataset, CategoryRenderer3D renderer, CategoryAxis3D rowAxis, CategoryAxis3D columnAxis, ValueAxis3D valueAxis) { Args.nullNotPermitted(dataset, "dataset"); Args.nullNotPermitted(renderer, "renderer"); Args.nullNotPermitted(rowAxis, "rowAxis"); Args.nullNotPermitted(columnAxis, "columnAxis"); Args.nullNotPermitted(valueAxis, "valueAxis"); this.dataset = dataset; this.dataset.addChangeListener(this); this.dimensions = calculateDimensions(); this.renderer = renderer; this.renderer.setPlot(this); this.renderer.addChangeListener(this); this.rowAxis = rowAxis; this.rowAxis.addChangeListener(this); this.columnAxis = columnAxis; this.columnAxis.addChangeListener(this); this.valueAxis = valueAxis; this.valueAxis.addChangeListener(this); this.rowAxis.configureAsRowAxis(this); this.columnAxis.configureAsColumnAxis(this); this.valueAxis.configureAsValueAxis(this); this.gridlinesVisibleForValues = true; this.gridlinesVisibleForColumns = false; this.gridlinesVisibleForRows = false; this.gridlinePaintForRows = Color.WHITE; this.gridlinePaintForColumns = Color.WHITE; this.gridlinePaintForValues = Color.WHITE; this.gridlineStrokeForRows = DEFAULT_GRIDLINE_STROKE; this.gridlineStrokeForColumns = DEFAULT_GRIDLINE_STROKE; this.gridlineStrokeForValues = DEFAULT_GRIDLINE_STROKE; this.legendLabelGenerator = new StandardCategoryLabelGenerator(); this.yDimensionOverride = null; this.toolTipGenerator = new StandardCategoryItemLabelGenerator(); } /** * Sets the flag that controls whether the plot's dimensions are * automatically calculated and, if {@code true}, sends a change event to * all registered listeners. * * @param auto the new flag value. * * @since 1.2 */ public void setAutoAdjustDimensions(boolean auto) { this.autoAdjustDimensions = auto; if (auto) { this.dimensions = calculateDimensions(); fireChangeEvent(true); } } /** * Sets the dimensions (in 3D space) for the plot, resets the * {@code autoAdjustDimensions} flag to {@code false}, and sends a * {@link Plot3DChangeEvent} to all registered listeners. * * @param dimensions the dimensions ({@code null} not permitted). * * @see Plot3D#getDimensions() */ public void setDimensions(Dimension3D dimensions) { Args.nullNotPermitted(dimensions, "dimensions"); this.dimensions = dimensions; this.autoAdjustDimensions = false; fireChangeEvent(true); } /** * Returns the dataset for the chart. * * @return The dataset (never {@code null}). */ public CategoryDataset3D getDataset() { return this.dataset; } /** * Sets the dataset and sends a {@link Plot3DChangeEvent} to all registered * listeners. When you call this method, the axes will be reconfigured for * the new data. * * @param dataset the dataset ({@code null} not permitted). */ public void setDataset(CategoryDataset3D dataset) { Args.nullNotPermitted(dataset, "dataset"); this.dataset.removeChangeListener(this); this.dataset = dataset; this.dataset.addChangeListener(this); // we send ourselves a dataset change event since this will // reconfigure the axes then trigger the required plot change event datasetChanged(new Dataset3DChangeEvent(this, this.dataset)); } /** * Returns the renderer (very often you will need to cast this to a specific * class to make customisations). * * @return The renderer (never {@code null}). */ public CategoryRenderer3D getRenderer() { return this.renderer; } /** * Sets the renderer and sends a change event to all registered listeners. * * @param renderer the renderer ({@code null} not permitted). */ public void setRenderer(CategoryRenderer3D renderer) { Args.nullNotPermitted(renderer, "renderer"); this.renderer.removeChangeListener(this); this.renderer = renderer; this.renderer.addChangeListener(this); // a new renderer might mean the axis range needs changing... this.valueAxis.configureAsValueAxis(this); fireChangeEvent(true); } /** * Returns the row axis. * * @return The row axis. */ public CategoryAxis3D getRowAxis() { return this.rowAxis; } /** * Sets the row axis and sends a {@link Plot3DChangeEvent} to all registered * listeners. The row axis is equivalent to the z-axis. * * @param axis the row axis ({@code null} not permitted). */ public void setRowAxis(CategoryAxis3D axis) { Args.nullNotPermitted(axis, "axis"); this.rowAxis.removeChangeListener(this); this.rowAxis = axis; this.rowAxis.addChangeListener(this); fireChangeEvent(true); } /** * Returns the column axis. * * @return The column axis (never {@code null}). */ public CategoryAxis3D getColumnAxis() { return this.columnAxis; } /** * Sets the column axis and sends a {@link Plot3DChangeEvent} to all * registered listeners. * * @param axis the new axis ({@code null} not permitted). * * @see #setRowAxis(org.jfree.chart3d.axis.CategoryAxis3D) * @see #setValueAxis(org.jfree.chart3d.axis.ValueAxis3D) * */ public void setColumnAxis(CategoryAxis3D axis) { Args.nullNotPermitted(axis, "axis"); this.columnAxis.removeChangeListener(this); this.columnAxis = axis; this.columnAxis.addChangeListener(this); fireChangeEvent(true); } /** * Returns the value axis (the vertical axis in the plot). * * @return The value axis (never {@code null}). */ public ValueAxis3D getValueAxis() { return this.valueAxis; } /** * Sets the value axis and sends a {@link Plot3DChangeEvent} to all * registered listeners. * * @param axis the axis ({@code null} not permitted). */ public void setValueAxis(ValueAxis3D axis) { Args.nullNotPermitted(axis, "axis"); this.valueAxis.removeChangeListener(this); this.valueAxis = axis; this.valueAxis.configureAsValueAxis(this); this.valueAxis.addChangeListener(this); fireChangeEvent(true); } /** * Returns {@code true} if gridlines are shown for the column axis and * {@code false} otherwise. The default value is {@code false}. * * @return A boolean. */ public boolean getGridlinesVisibleForRows() { return this.gridlinesVisibleForRows; } /** * Sets the flag that controls whether or not gridlines are shown for the * row axis and sends a {@link Plot3DChangeEvent} to all registered * listeners. * * @param visible the new flag value. */ public void setGridlinesVisibleForRows(boolean visible) { this.gridlinesVisibleForRows = visible; fireChangeEvent(false); } /** * Returns the paint used to draw the gridlines for the row axis, if they * are visible. * * @return The paint (never {@code null}). */ public Paint getGridlinePaintForRows() { return this.gridlinePaintForRows; } /** * Sets the paint used for the row axis gridlines and sends a * {@link Plot3DChangeEvent} to all registered listeners. * * @param paint the paint ({@code null} not permitted). */ public void setGridlinePaintForRows(Paint paint) { Args.nullNotPermitted(paint, "paint"); this.gridlinePaintForRows = paint; fireChangeEvent(false); } /** * Returns the stroke for the gridlines associated with the row axis. The * default value is {@code BasicStroke(0.5f, BasicStroke.CAP_ROUND, * BasicStroke.JOIN_ROUND, 1f, new float[] { 3f, 3f }, 0f)}. * * @return The stroke (never {@code null}). */ public Stroke getGridlineStrokeForRows() { return this.gridlineStrokeForRows; } /** * Sets the stroke used to draw the gridlines for the row axis, if they are * visible, and sends a {@link Plot3DChangeEvent} to all registered * listeners. * * @param stroke the stroke ({@code null} not permitted). */ public void setGridlineStrokeForRows(Stroke stroke) { Args.nullNotPermitted(stroke, "stroke"); this.gridlineStrokeForRows = stroke; fireChangeEvent(false); } /** * Returns {@code true} if gridlines are shown for the column axis and * {@code false} otherwise. The default value is {@code false}. * * @return A boolean. */ public boolean getGridlinesVisibleForColumns() { return this.gridlinesVisibleForColumns; } /** * Sets the flag that controls whether or not gridlines are shown for the * column axis and sends a {@link Plot3DChangeEvent} to all registered * listeners. * * @param visible the new flag value. */ public void setGridlinesVisibleForColumns(boolean visible) { this.gridlinesVisibleForColumns = visible; fireChangeEvent(false); } /** * Returns {@code true} if gridlines are shown for the column axis and * {@code false} otherwise. The default value is {@code true}. * * @return A boolean. */ public boolean getGridlinesVisibleForValues() { return this.gridlinesVisibleForValues; } /** * Sets the flag that controls whether or not gridlines are shown for the * value axis and sends a {@link Plot3DChangeEvent} to all registered * listeners. * * @param visible the new flag value. */ public void setGridlinesVisibleForValues(boolean visible) { this.gridlinesVisibleForValues = visible; fireChangeEvent(false); } /** * Returns the paint for the gridlines associated with the value axis. The * default value is {@code Color.WHITE}. * * @return The paint for value axis gridlines (never {@code null}). */ public Paint getGridlinePaintForValues() { return this.gridlinePaintForValues; } /** * Sets the paint used for the value axis gridlines and sends a * {@link Plot3DChangeEvent} to all registered listeners. * * @param paint the paint ({@code null} not permitted). */ public void setGridlinePaintForValues(Paint paint) { Args.nullNotPermitted(paint, "paint"); this.gridlinePaintForValues = paint; fireChangeEvent(false); } /** * Returns the stroke for the gridlines associated with the value axis. The * default value is {@code BasicStroke(0.5f, BasicStroke.CAP_ROUND, * BasicStroke.JOIN_ROUND, 1f, new float[] { 3f, 3f }, 0f)}. * * @return The stroke (never {@code null}). */ public Stroke getGridlineStrokeForValues() { return this.gridlineStrokeForValues; } /** * Sets the stroke used to draw the grid lines for the value axis, if they * are visible, and sends a {@link Plot3DChangeEvent} to all registered * listeners. * * @param stroke the stroke ({@code null} not permitted). */ public void setGridlineStrokeForValues(Stroke stroke) { Args.nullNotPermitted(stroke, "stroke"); this.gridlineStrokeForValues = stroke; fireChangeEvent(false); } /** * Returns the paint used to draw the grid lines for the column axis, if * they are visible. The default value is {@code Color.WHITE}. * * @return The paint (never {@code null}). */ public Paint getGridlinePaintForColumns() { return this.gridlinePaintForColumns; } /** * Sets the paint used to draw the grid lines for the column axis, if they * are visible, and sends a {@link Plot3DChangeEvent} to all registered * listeners. * * @param paint the paint ({@code null} not permitted). */ public void setGridlinePaintForColumns(Paint paint) { Args.nullNotPermitted(paint, "paint"); this.gridlinePaintForColumns = paint; fireChangeEvent(false); } /** * Returns the stroke for the gridlines associated with the column axis. The * default value is {@code BasicStroke(0.5f, BasicStroke.CAP_ROUND, * BasicStroke.JOIN_ROUND, 1f, new float[] { 3f, 3f }, 0f)}. * * @return The stroke (never {@code null}). */ public Stroke getGridlineStrokeForColumns() { return this.gridlineStrokeForColumns; } /** * Sets the stroke used to draw the grid lines for the column axis, if they * are visible, and sends a {@link Plot3DChangeEvent} to all registered * listeners. * * @param stroke the stroke ({@code null} not permitted). */ public void setGridlineStrokeForColumns(Stroke stroke) { Args.nullNotPermitted(stroke, "stroke"); this.gridlineStrokeForColumns = stroke; fireChangeEvent(false); } /** * Returns the legend label generator, an object that converts key values in * the dataset into corresponding strings for presentation in the chart. * * @return The legend label generator (never {@code null}). * * @since 1.2 */ public CategoryLabelGenerator getLegendLabelGenerator() { return this.legendLabelGenerator; } /** * Sets the legend label generator and sends a {@link Plot3DChangeEvent} to * all registered listeners. * * @param generator the generator ({@code null} not permitted). * * @since 1.2 */ public void setLegendLabelGenerator(CategoryLabelGenerator generator) { Args.nullNotPermitted(generator, "generator"); this.legendLabelGenerator = generator; fireChangeEvent(false); } /** * Returns the y-dimension override. The default value is {@code null}, * which means that when the plot dimensions are automatically calculated, * the height of the plot will be set to the greater of the width and the * depth. * * @return The y-dimension override (possibly {@code null}). * * @since 1.2 */ public Double getYDimensionOverride() { return this.yDimensionOverride; } /** * Sets the y-dimension override and, if the {@code autoAdjustDimensions} * flag is set, recalculates the dimensions and sends a * {@link Plot3DChangeEvent} to all registered listeners. * * @param dim the new y-dimension override ({@code null} permitted). * * @since 1.2 */ public void setYDimensionOverride(Double dim) { this.yDimensionOverride = dim; if (this.autoAdjustDimensions) { this.dimensions = calculateDimensions(); fireChangeEvent(true); } } /** * Returns the tool tip generator. This is an object that calculates and * returns a string (that will be used as the tool tip) for any given data * value in the dataset. * * @return The tool tip generator (possibly {@code null}). * * @since 1.3 */ public CategoryItemLabelGenerator getToolTipGenerator() { return this.toolTipGenerator; } /** * Sets the tool tip generator and sends a {@link Plot3DChangeEvent} to all * registered listeners. * * @param generator the new generator ({@code null} permitted). * * @since 1.3 */ public void setToolTipGenerator(CategoryItemLabelGenerator generator) { this.toolTipGenerator = generator; fireChangeEvent(false); } /** * Returns a list containing legend item info, typically one item for each * series in the chart. This is intended for use in the construction of a * chart legend. * * @return A list containing legend item info (possibly empty but never * {@code null}). */ @Override @SuppressWarnings("unchecked") // we don't know the dataset generic types public List getLegendInfo() { List result = new ArrayList<>(); List> keys = this.dataset.getSeriesKeys(); for (Comparable key : keys) { int series = this.dataset.getSeriesIndex(key); Color color = this.renderer.getColorSource().getLegendColor(series); String seriesLabel = this.legendLabelGenerator.generateSeriesLabel( this.dataset, key); LegendItemInfo info = new StandardLegendItemInfo(key, seriesLabel, color); result.add(info); } return result; } @Override public void compose(World world, double xOffset, double yOffset, double zOffset) { for (int series = 0; series < this.dataset.getSeriesCount(); series++) { for (int row = 0; row < this.dataset.getRowCount(); row++) { for (int column = 0; column < this.dataset.getColumnCount(); column++) { this.renderer.composeItem(this.dataset, series, row, column, world, getDimensions(), xOffset, yOffset, zOffset); } } } } @Override public String generateToolTipText(ItemKey itemKey) { if (!(itemKey instanceof KeyedValues3DItemKey)) { throw new IllegalArgumentException( "The itemKey must be a Values3DItemKey instance."); } KeyedValues3DItemKey vik = (KeyedValues3DItemKey) itemKey; return this.toolTipGenerator.generateItemLabel(dataset, vik.getSeriesKey(), vik.getRowKey(), vik.getColumnKey()); } /** * Accepts a visitor for the plot. This method first calls the * {@code receive()} method for each of the plot's axes and the renderer, * then performs the visitor's function on the plot. This is a general * purpose mechanism, but the main use is to apply chart style changes * across all the elements of a chart. * * @param visitor the visitor ({@code null} not permitted). * * @since 1.2 */ @Override public void receive(ChartElementVisitor visitor) { this.columnAxis.receive(visitor); this.rowAxis.receive(visitor); this.valueAxis.receive(visitor); this.renderer.receive(visitor); visitor.visit(this); } /** * Tests this plot for equality with an arbitrary object. * * @param obj the object ({@code null} permitted). * * @return A boolean. */ @Override public boolean equals(Object obj) { if (obj == this) { return true; } if (!(obj instanceof CategoryPlot3D)) { return false; } CategoryPlot3D that = (CategoryPlot3D) obj; if (this.gridlinesVisibleForRows != that.gridlinesVisibleForRows) { return false; } if (!this.gridlineStrokeForRows.equals(that.gridlineStrokeForRows)) { return false; } if (!ObjectUtils.equalsPaint(this.gridlinePaintForRows, that.gridlinePaintForRows)) { return false; } if (this.gridlinesVisibleForColumns != that.gridlinesVisibleForColumns) { return false; } if (!this.gridlineStrokeForColumns.equals( that.gridlineStrokeForColumns)) { return false; } if (!ObjectUtils.equalsPaint(this.gridlinePaintForColumns, that.gridlinePaintForColumns)) { return false; } if (this.gridlinesVisibleForValues != that.gridlinesVisibleForValues) { return false; } if (!this.gridlineStrokeForValues.equals(that.gridlineStrokeForValues)) { return false; } if (!ObjectUtils.equalsPaint(this.gridlinePaintForValues, that.gridlinePaintForValues)) { return false; } if (!this.legendLabelGenerator.equals(that.legendLabelGenerator)) { return false; } if (!ObjectUtils.equals(this.yDimensionOverride, that.yDimensionOverride)) { return false; } if (!ObjectUtils.equals(this.toolTipGenerator, that.toolTipGenerator)) { return false; } return super.equals(obj); } /** * Receives notification of a change to the dataset and handles this by * adjusting the plot dimensions (according to the setting of the * {@code autoAdjustDimensions} flag), reconfiguring the axes, and * propagating a {@code Plot3DChangeEvent}. * * @param event the change event. */ @Override public void datasetChanged(Dataset3DChangeEvent event) { // update the category axis labels // and the value axis range if (this.autoAdjustDimensions) { this.dimensions = calculateDimensions(); } this.columnAxis.configureAsColumnAxis(this); this.rowAxis.configureAsRowAxis(this); this.valueAxis.configureAsValueAxis(this); super.datasetChanged(event); // propagates a plot change event } /** * Returns the dimensions for the plot that best suit the current data * values. The x-dimension is set to the number of columns in the dataset * and the z-dimension is set to the number of rows in the dataset. For the * y-dimension, the code first checks the {@code yDimensionOverride} * attribute to see if a specific value is requested...and if not, the * minimum of the x and z dimensions will be used. * * @return The dimensions (never {@code null}). */ private Dimension3D calculateDimensions() { double depth = Math.max(1.0, this.dataset.getRowCount() + 1); double width = Math.max(1.0, this.dataset.getColumnCount() + 1); double height = Math.max(1.0, Math.min(width, depth)); if (this.yDimensionOverride != null) { height = this.yDimensionOverride; } return new Dimension3D(width, height, depth); } /** * Receives notification that one of the axes has been changed. This will * trigger a {@link Plot3DChangeEvent} that will usually cause the chart to * be repainted. * * @param event the change event. */ @Override public void axisChanged(Axis3DChangeEvent event) { // for now we just fire a plot change event which will flow up the // chain and eventually trigger a chart repaint fireChangeEvent(event.requiresWorldUpdate()); } /** * Receives notification that the renderer has been modified in some way. * This will trigger a {@link Plot3DChangeEvent} that will usually cause the * chart to be repainted. * * @param event information about the event. */ @Override public void rendererChanged(Renderer3DChangeEvent event) { // for now we just fire a plot change event which will flow up the // chain and eventually trigger a chart repaint fireChangeEvent(event.requiresWorldUpdate()); } /** * Provides serialization support. * * @param stream the output stream. * * @throws IOException if there is an I/O error. */ private void writeObject(ObjectOutputStream stream) throws IOException { stream.defaultWriteObject(); SerialUtils.writePaint(this.gridlinePaintForRows, stream); SerialUtils.writePaint(this.gridlinePaintForColumns, stream); SerialUtils.writePaint(this.gridlinePaintForValues, stream); SerialUtils.writeStroke(this.gridlineStrokeForRows, stream); SerialUtils.writeStroke(this.gridlineStrokeForColumns, stream); SerialUtils.writeStroke(this.gridlineStrokeForValues, stream); } /** * Provides serialization support. * * @param stream the input stream. * * @throws IOException if there is an I/O error. * @throws ClassNotFoundException if there is a classpath problem. */ private void readObject(ObjectInputStream stream) throws IOException, ClassNotFoundException { stream.defaultReadObject(); this.gridlinePaintForRows = SerialUtils.readPaint(stream); this.gridlinePaintForColumns = SerialUtils.readPaint(stream); this.gridlinePaintForValues = SerialUtils.readPaint(stream); this.gridlineStrokeForRows = SerialUtils.readStroke(stream); this.gridlineStrokeForColumns = SerialUtils.readStroke(stream); this.gridlineStrokeForValues = SerialUtils.readStroke(stream); } } orson-charts-2.1.0/src/main/java/org/jfree/chart3d/plot/ColorSource.java000066400000000000000000000054741417331271500261000ustar00rootroot00000000000000/* =========================================================== * Orson Charts : a 3D chart library for the Java(tm) platform * =========================================================== * * (C)opyright 2013-2022, by David Gilbert. All rights reserved. * * https://github.com/jfree/orson-charts * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . * * [Oracle and Java are registered trademarks of Oracle and/or its affiliates. * Other names may be trademarks of their respective owners.] * * If you do not wish to be bound by the terms of the GPL, an alternative * commercial license can be purchased. For details, please see visit the * Orson Charts home page: * * http://www.object-refinery.com/orsoncharts/index.html * */ package org.jfree.chart3d.plot; import java.awt.Color; /** * A color source for use by the {@link PiePlot3D} class. This is the * interface through which the plot will obtain colors for each data item * (segment) in the chart. A default implementation * ({@link StandardColorSource}) is provided. */ public interface ColorSource> { /** * Returns the color for one data item in the chart. We return a * {@code Color} rather than a paint, because some manipulations * that require a {@code Color} instance are done for the shading * during the 3D rendering. * * @param key the key ({@code null} not permitted). * * @return The color. */ Color getColor(K key); /** * Sets the color associated with the specified key. If the supplied * color is {@code null}, this will have the effect of clearing any * previous setting and reverting to the default color. * * @param key the key ({@code null} not permitted). * @param color the color ({@code null} permitted). */ void setColor(K key, Color color); /** * Restyles the source using the specified colors. Refer to the * implementing class to confirm the precise behaviour (typically all * existing color settings are cleared and the specified colors are * installed as the new defaults). * * @param colors the colors. * * @since 1.2 */ void style(Color... colors); } orson-charts-2.1.0/src/main/java/org/jfree/chart3d/plot/FontSource.java000066400000000000000000000047651417331271500257320ustar00rootroot00000000000000/* =========================================================== * Orson Charts : a 3D chart library for the Java(tm) platform * =========================================================== * * (C)opyright 2013-2022, by David Gilbert. All rights reserved. * * https://github.com/jfree/orson-charts * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . * * [Oracle and Java are registered trademarks of Oracle and/or its affiliates. * Other names may be trademarks of their respective owners.] * * If you do not wish to be bound by the terms of the GPL, an alternative * commercial license can be purchased. For details, please see visit the * Orson Charts home page: * * http://www.object-refinery.com/orsoncharts/index.html * */ package org.jfree.chart3d.plot; import java.awt.Font; /** * An object that supplies {@code Font} instances associated with * keys. This is used by the {@link PiePlot3D} class to obtain section label * fonts for each data item(segment) in the chart. A default implementation * ({@link StandardFontSource}) is provided. */ public interface FontSource { /** * Returns a font based on the supplied key. * * @param key the key ({@code null} not permitted). * * @return A font (never {@code null}). */ Font getFont(K key); /** * Sets the font associated with a key. * * @param key the key ({@code null} not permitted). * @param font the font ({@code null} not permitted). */ void setFont(K key, Font font); /** * Restyles the source using the specified font. Refer to the implementing * class to confirm the precise behaviour (typically all existing font * settings are cleared and this font is installed as the new default * section label font). * * @param font the font ({@code null} not permitted). * * @since 1.2 */ void style(Font font); }orson-charts-2.1.0/src/main/java/org/jfree/chart3d/plot/PiePlot3D.java000066400000000000000000000462151417331271500254020ustar00rootroot00000000000000/* =========================================================== * Orson Charts : a 3D chart library for the Java(tm) platform * =========================================================== * * (C)opyright 2013-2022, by David Gilbert. All rights reserved. * * https://github.com/jfree/orson-charts * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . * * [Oracle and Java are registered trademarks of Oracle and/or its affiliates. * Other names may be trademarks of their respective owners.] * * If you do not wish to be bound by the terms of the GPL, an alternative * commercial license can be purchased. For details, please see visit the * Orson Charts home page: * * http://www.object-refinery.com/orsoncharts/index.html * */ package org.jfree.chart3d.plot; import java.awt.Color; import java.awt.Font; import java.io.Serializable; import java.util.ArrayList; import java.util.List; import org.jfree.chart3d.internal.Args; import org.jfree.chart3d.Chart3D; import org.jfree.chart3d.Chart3DFactory; import org.jfree.chart3d.ChartElementVisitor; import org.jfree.chart3d.data.DataUtils; import org.jfree.chart3d.data.ItemKey; import org.jfree.chart3d.data.KeyedValuesItemKey; import org.jfree.chart3d.data.PieDataset3D; import org.jfree.chart3d.graphics3d.Dimension3D; import org.jfree.chart3d.graphics3d.Dot3D; import org.jfree.chart3d.graphics3d.Object3D; import org.jfree.chart3d.graphics3d.World; import org.jfree.chart3d.label.PieLabelGenerator; import org.jfree.chart3d.label.StandardPieLabelGenerator; import org.jfree.chart3d.legend.LegendItemInfo; import org.jfree.chart3d.legend.StandardLegendItemInfo; /** * A plot for creating 3D pie charts. To create a pie chart, you can use the * {@code createPieChart()} method in the {@link Chart3DFactory} class. * A typical pie chart will look like this: *

* PieChart3DDemo1.svg *
*

* NOTE: This class is serializable, but the serialization format is subject * to change in future releases and should not be relied upon for persisting * instances of this class. */ @SuppressWarnings("serial") public class PiePlot3D extends AbstractPlot3D implements Serializable { /** The default font for section labels on the chart. */ public static final Font DEFAULT_SECTION_LABEL_FONT = new Font("Dialog", Font.PLAIN, 14); /** The dataset. */ private PieDataset3D dataset; /** The radius of the pie chart. */ private double radius; /** The depth of the pie chart. */ private double depth; /** The section color source. */ private ColorSource sectionColorSource; /** The section label generator. */ private PieLabelGenerator sectionLabelGenerator; /** The font source used to determine the font for section labels. */ private FontSource sectionLabelFontSource; /** * The color source used to determine the foreground color for section * labels. */ private ColorSource sectionLabelColorSource; /** The legend label generator. */ private PieLabelGenerator legendLabelGenerator; /** * The tool tip generator (can be null, in which case there will be no * tool tips. */ private PieLabelGenerator toolTipGenerator; /** * The number of segments used to render 360 degrees of the pie. A higher * number will give better output but slower performance. */ private int segments = 40; /** * Creates a new pie plot in 3D. * * @param dataset the dataset ({@code null} not permitted). */ public PiePlot3D(PieDataset3D dataset) { Args.nullNotPermitted(dataset, "dataset"); this.dataset = dataset; this.dataset.addChangeListener(this); this.radius = 4.0; this.depth = 0.5; this.sectionColorSource = new StandardColorSource(); this.sectionLabelGenerator = new StandardPieLabelGenerator( StandardPieLabelGenerator.KEY_ONLY_TEMPLATE); this.sectionLabelFontSource = new StandardFontSource( DEFAULT_SECTION_LABEL_FONT); this.sectionLabelColorSource = new StandardColorSource(Color.BLACK); this.legendLabelGenerator = new StandardPieLabelGenerator(); this.toolTipGenerator = new StandardPieLabelGenerator( StandardPieLabelGenerator.PERCENT_TEMPLATE_2DP); } /** * Returns the dataset. * * @return The dataset (never {@code null}). */ public PieDataset3D getDataset() { return this.dataset; } /** * Sets the dataset and notifies registered listeners that the dataset has * been updated. * * @param dataset the dataset ({@code null} not permitted). */ public void setDataset(PieDataset3D dataset) { Args.nullNotPermitted(dataset, "dataset"); this.dataset.removeChangeListener(this); this.dataset = dataset; this.dataset.addChangeListener(this); fireChangeEvent(true); } /** * Returns the radius of the pie (the default value is 8.0). * * @return The radius of the pie. */ public double getRadius() { return this.radius; } /** * Sets the radius of the pie chart and sends a change event to all * registered listeners. * * @param radius the radius. */ public void setRadius(double radius) { this.radius = radius; fireChangeEvent(true); } /** * Returns the depth of the pie (the default value is 2.0). * * @return The depth of the pie. */ public double getDepth() { return this.depth; } /** * Sets the depth of the pie chart and sends a change event to all * registered listeners. * * @param depth the depth. */ public void setDepth(double depth) { this.depth = depth; fireChangeEvent(true); } /** * Returns the color source for section colors. * * @return The color source (never {@code null}). */ public ColorSource getSectionColorSource() { return this.sectionColorSource; } /** * Sets the color source and sends a {@link Plot3DChangeEvent} to all * registered listeners. * * @param source the color source ({@code null} not permitted). */ public void setSectionColorSource(ColorSource source) { Args.nullNotPermitted(source, "source"); this.sectionColorSource = source; fireChangeEvent(true); } /** * Sets a new color source for the plot using the specified colors and * sends a {@link Plot3DChangeEvent} to all registered listeners. This * is a convenience method that is equivalent to * {@code setSectionColorSource(new StandardColorSource(colors))}. * * @param colors one or more colors ({@code null} not permitted). * * @since 1.2 */ public void setSectionColors(Color... colors) { setSectionColorSource(new StandardColorSource(colors)); } /** * Returns the object that creates labels for each section of the pie * chart. * * @return The section label generator (never {@code null}). * * @since 1.2 */ public PieLabelGenerator getSectionLabelGenerator() { return this.sectionLabelGenerator; } /** * Sets the object that creates labels for each section of the pie chart, * and sends a {@link Plot3DChangeEvent} to all registered listeners. * * @param generator the generator ({@code null} not permitted). * * @since 1.2 */ public void setSectionLabelGenerator(PieLabelGenerator generator) { Args.nullNotPermitted(generator, "generator"); this.sectionLabelGenerator = generator; fireChangeEvent(false); } /** * Returns the font source that is used to determine the font to use for * the section labels. * * @return The font source for the section labels (never {@code null}). */ public FontSource getSectionLabelFontSource() { return this.sectionLabelFontSource; } /** * Sets the font source and sends a {@link Plot3DChangeEvent} to all * registered listeners. * * @param source the source ({@code null} not permitted). */ public void setSectionLabelFontSource(FontSource source) { Args.nullNotPermitted(source, "source"); this.sectionLabelFontSource = source; fireChangeEvent(false); } /** * Returns the color source for section labels. The default value is * an instance of {@link StandardColorSource} that always returns * {@code Color.BLACK}. * * @return The color source (never {@code null}). * * @see #setSectionLabelColorSource(ColorSource) */ public ColorSource getSectionLabelColorSource() { return this.sectionLabelColorSource; } /** * Sets the color source for the section labels and sends a * {@link Plot3DChangeEvent} to all registered listeners. * * @param source the color source. * * @see #getSectionLabelColorSource() */ public void setSectionLabelColorSource(ColorSource source) { Args.nullNotPermitted(source, "source"); this.sectionLabelColorSource = source; fireChangeEvent(false); } /** * Returns the object that creates legend labels for each section of the pie * chart. * * @return The legend label generator (never {@code null}). * * @since 1.2 */ public PieLabelGenerator getLegendLabelGenerator() { return this.legendLabelGenerator; } /** * Sets the object that creates legend labels for each section of the pie * chart, and sends a {@link Plot3DChangeEvent} to all registered * listeners. * * @param generator the generator ({@code null} not permitted). * * @since 1.2 */ public void setLegendLabelGenerator(PieLabelGenerator generator) { Args.nullNotPermitted(generator, "generator"); this.legendLabelGenerator = generator; fireChangeEvent(false); } /** * Returns the tool tip generator. * * @return The tool tip generator (possibly {@code null}). * * @since 1.3 */ public PieLabelGenerator getToolTipGenerator() { return this.toolTipGenerator; } /** * Sets the tool tip generator and sends a change event to all registered * listeners. * * @param generator the generator ({@code null} permitted). * * @since 1.3 */ public void setToolTipGenerator(PieLabelGenerator generator) { this.toolTipGenerator = generator; fireChangeEvent(false); } /** * Returns the dimensions for the plot. For the pie chart, it is more * natural to specify the dimensions in terms of a radius and a depth, so * we use those values to calculate the dimensions here. * * @return The dimensions for the plot. */ @Override public Dimension3D getDimensions() { return new Dimension3D(this.radius * 2, this.depth, this.radius * 2); } /** * Returns the number of segments used when composing the 3D objects * representing the pie chart. The default value is {@code 40}. * * @return The number of segments used to compose the pie chart. */ public int getSegmentCount() { return this.segments; } /** * Sets the number of segments used when composing the pie chart and * sends a {@link Plot3DChangeEvent} to all registered listeners. A higher * number will result in a more rounded pie chart, but will take longer * to render. * * @param count the count. */ public void setSegmentCount(int count) { this.segments = count; fireChangeEvent(true); } /** * Returns a list containing legend item info, typically one item for * each series in the chart. This is intended for use in the construction * of a chart legend. * * @return A list containing legend item info. */ @Override @SuppressWarnings("unchecked") public List getLegendInfo() { List result = new ArrayList<>(); for (Comparable key : this.dataset.getKeys()) { String label = this.legendLabelGenerator.generateLabel(dataset, key); LegendItemInfo info = new StandardLegendItemInfo(key, label, this.sectionColorSource.getColor(key)); result.add(info); } return result; } /** * Adds 3D objects representing the current data for the plot to the * specified world. After the world has been populated (or constructed) in * this way, it is ready for rendering. This method is called by the * {@link Chart3D} class, you won't normally call it directly. * * @param world the world ({@code null} not permitted). * @param xOffset the x-offset. * @param yOffset the y-offset. * @param zOffset the z-offset. */ @Override @SuppressWarnings("unchecked") public void compose(World world, double xOffset, double yOffset, double zOffset) { double total = DataUtils.total(this.dataset); double r = 0.0; int count = this.dataset.getItemCount(); for (int i = 0; i < count; i++) { Comparable key = this.dataset.getKey(i); Number n = this.dataset.getValue(i); if (n != null) { double angle = Math.PI * 2 * (n.doubleValue() / total); Color c = this.sectionColorSource.getColor( this.dataset.getKey(i)); Object3D segment = Object3D.createPieSegment(this.radius, 0.0, yOffset, this.depth, r, r + angle, Math.PI / this.segments, c); segment.setProperty(Object3D.ITEM_KEY, new KeyedValuesItemKey(key)); world.add(segment); r = r + angle; } } } /** * Returns a list of label faces for the plot. These are non-visible * objects added to the 3D model of the pie chart to track the positions * for labels (which are added after the plot is projected and rendered). *

* NOTE: This method is public so that it can be called by the * {@link Chart3D} class - you won't normally call it directly. * * @param xOffset the x-offset. * @param yOffset the y-offset. * @param zOffset the z-offset. * * @return A list of label faces. */ public List getLabelFaces(double xOffset, double yOffset, double zOffset) { double total = DataUtils.total(this.dataset); List result = new ArrayList<>(); // this adds the centre points result.add(new Dot3D(0.0f, 0.0f, 0.0f, Color.RED)); result.add(new Dot3D(0.0f, (float) yOffset, 0.0f, Color.RED)); double r = 0.0; int count = this.dataset.getItemCount(); for (int i = 0; i < count; i++) { Number n = this.dataset.getValue(i); double angle = 0.0; if (n != null) { angle = Math.PI * 2 * (n.doubleValue() / total); } result.addAll(Object3D.createPieLabelMarkers(this.radius * 1.2, 0.0, yOffset - this.depth * 0.05, this.depth * 1.1, r, r + angle)); r = r + angle; } return result; } @Override public String generateToolTipText(ItemKey itemKey) { if (!(itemKey instanceof KeyedValuesItemKey)) { throw new IllegalArgumentException( "The itemKey must be a ValuesItemKey instance."); } KeyedValuesItemKey vik = (KeyedValuesItemKey) itemKey; return this.toolTipGenerator.generateLabel(this.dataset, vik.getKey()); } /** * Receives a visitor. This is a general purpose mechanism, but the main * use is to apply chart style changes across all the elements of a * chart. * * @param visitor the visitor ({@code null} not permitted). * * @since 1.2 */ @Override public void receive(ChartElementVisitor visitor) { visitor.visit(this); } /** * Tests this plot for equality with an arbitrary object. Note that the * plot's dataset is NOT considered in the equality test. * * @param obj the object ({@code null} not permitted). * * @return A boolean. */ @Override public boolean equals(Object obj) { if (obj == this) { return true; } if (!(obj instanceof PiePlot3D)) { return false; } PiePlot3D that = (PiePlot3D) obj; if (this.radius != that.radius) { return false; } if (this.depth != that.depth) { return false; } if (!this.sectionColorSource.equals(that.sectionColorSource)) { return false; } if (!this.sectionLabelGenerator.equals(that.sectionLabelGenerator)) { return false; } if (!this.sectionLabelFontSource.equals(that.sectionLabelFontSource)) { return false; } if (!this.sectionLabelColorSource.equals( that.sectionLabelColorSource)) { return false; } if (!this.legendLabelGenerator.equals(that.legendLabelGenerator)) { return false; } if (!this.toolTipGenerator.equals(that.toolTipGenerator)) { return false; } if (this.segments != that.segments) { return false; } return super.equals(obj); } @Override public int hashCode() { int hash = 5; hash = 97 * hash + (int) (Double.doubleToLongBits(this.radius) ^ (Double.doubleToLongBits(this.radius) >>> 32)); hash = 97 * hash + (int) (Double.doubleToLongBits(this.depth) ^ (Double.doubleToLongBits(this.depth) >>> 32)); hash = 97 * hash + this.sectionColorSource.hashCode(); hash = 97 * hash + this.sectionLabelGenerator.hashCode(); hash = 97 * hash + this.sectionLabelFontSource.hashCode(); hash = 97 * hash + this.sectionLabelColorSource.hashCode(); hash = 97 * hash + this.segments; return hash; } } orson-charts-2.1.0/src/main/java/org/jfree/chart3d/plot/Plot3D.java000066400000000000000000000106101417331271500247320ustar00rootroot00000000000000/* =========================================================== * Orson Charts : a 3D chart library for the Java(tm) platform * =========================================================== * * (C)opyright 2013-2022, by David Gilbert. All rights reserved. * * https://github.com/jfree/orson-charts * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . * * [Oracle and Java are registered trademarks of Oracle and/or its affiliates. * Other names may be trademarks of their respective owners.] * * If you do not wish to be bound by the terms of the GPL, an alternative * commercial license can be purchased. For details, please see visit the * Orson Charts home page: * * http://www.object-refinery.com/orsoncharts/index.html * */ package org.jfree.chart3d.plot; import java.util.List; import org.jfree.chart3d.Chart3D; import org.jfree.chart3d.ChartElement; import org.jfree.chart3d.data.ItemKey; import org.jfree.chart3d.graphics3d.Dimension3D; import org.jfree.chart3d.graphics3d.World; import org.jfree.chart3d.legend.LegendItemInfo; /** * A plot for a {@link Chart3D}. In Orson Charts, the {@code Chart3D} is * the umbrella object for all charts, but it is the {@code Plot3D} * instance that determines the real structure of the chart. Built-in * implementations include {@link PiePlot3D}, {@link CategoryPlot3D} and * {@link XYZPlot}. */ public interface Plot3D extends ChartElement { /** * Returns the chart that the plot is assigned to, if any. * * @return The chart (possibly {@code null}). * * @since 1.2 */ Chart3D getChart(); /** * Sets the chart that the plot is assigned to. This method is intended * for use by the framework, you should not need to call it yourself. * * @param chart the chart ({@code null} permitted). * * @since 1.2 */ void setChart(Chart3D chart); /** * Returns the dimensions for the plot in the 3D world in which it will * be composed. * * @return The dimensions (never {@code null}). */ Dimension3D getDimensions(); /** * Adds 3D objects representing the current data for the plot to the * specified world. After the world has been populated (or constructed) in * this way, it is ready for rendering. * * @param world the world ({@code null} not permitted). * @param xOffset the x-offset. * @param yOffset the y-offset. * @param zOffset the z-offset. */ void compose(World world, double xOffset, double yOffset, double zOffset); /** * Returns a list containing legend item info, typically one item for * each series in the chart. This is intended for use in the construction * of a chart legend. *

* If you are implementing a new plot type that does not require a legend, * return an empty list. * * @return A list containing legend item info (never {@code null}). */ List getLegendInfo(); /** * Returns the tool tip text for the specified data item, or * {@code null} if no tool tip is required. * * @param itemKey the item key ({@code null} not permitted). * * @return The tool tip text (possibly {@code null}). * * @since 1.3 */ String generateToolTipText(ItemKey itemKey); /** * Registers a listener to receive notification of changes to the plot. * * @param listener the listener ({@code null} not permitted). */ void addChangeListener(Plot3DChangeListener listener); /** * De-registers a listener so that it no longer receives notification of * changes to the plot. * * @param listener the listener ({@code null} not permitted). */ void removeChangeListener(Plot3DChangeListener listener); } orson-charts-2.1.0/src/main/java/org/jfree/chart3d/plot/Plot3DChangeEvent.java000066400000000000000000000067511417331271500270550ustar00rootroot00000000000000/* =========================================================== * Orson Charts : a 3D chart library for the Java(tm) platform * =========================================================== * * (C)opyright 2013-2022, by David Gilbert. All rights reserved. * * https://github.com/jfree/orson-charts * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . * * [Oracle and Java are registered trademarks of Oracle and/or its affiliates. * Other names may be trademarks of their respective owners.] * * If you do not wish to be bound by the terms of the GPL, an alternative * commercial license can be purchased. For details, please see visit the * Orson Charts home page: * * http://www.object-refinery.com/orsoncharts/index.html * */ package org.jfree.chart3d.plot; import java.util.EventObject; import org.jfree.chart3d.Chart3D; import org.jfree.chart3d.data.Dataset3DChangeEvent; import org.jfree.chart3d.internal.Args; /** * An event used to signal a change to a {@link Plot3D}. Any object that * implements the {@link Plot3DChangeListener} interface can register with a * plot to receive change notifications. By default, the {@link Chart3D} * object will register with the plot it manages to monitor changes to the plot * and its subcomponents. *

* NOTE: This class is serializable, but the serialization format is subject * to change in future releases and should not be relied upon for persisting * instances of this class. */ @SuppressWarnings("serial") public class Plot3DChangeEvent extends EventObject { /** The plot. */ private final Plot3D plot; /** Does the plot change require the world to be updated? */ private final boolean requiresWorldUpdate; /** * Creates a new event. The {@code source} of the event can be * either the plot instance or another event that was received by the * plot (for example, a {@link Dataset3DChangeEvent}). * * @param source the event source ({@code null} not permitted). * @param plot the plot ({@code null} not permitted). * @param requiresWorldUpdate a flag that indicates whether or not the * world requires updating because of this change. */ public Plot3DChangeEvent(Object source, Plot3D plot, boolean requiresWorldUpdate) { super(source); Args.nullNotPermitted(plot, "plot"); this.plot = plot; this.requiresWorldUpdate = requiresWorldUpdate; } /** * Returns the plot from which the event came. * * @return The plot (never {@code null}). */ public Plot3D getPlot() { return this.plot; } /** * Returns the flag indicating whether or not this change event * requires the world to be updated/recreated. * * @return A boolean. * * @since 1.2 */ public boolean requiresWorldUpdate() { return this.requiresWorldUpdate; } } orson-charts-2.1.0/src/main/java/org/jfree/chart3d/plot/Plot3DChangeListener.java000066400000000000000000000037141417331271500275550ustar00rootroot00000000000000/* =========================================================== * Orson Charts : a 3D chart library for the Java(tm) platform * =========================================================== * * (C)opyright 2013-2022, by David Gilbert. All rights reserved. * * https://github.com/jfree/orson-charts * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . * * [Oracle and Java are registered trademarks of Oracle and/or its affiliates. * Other names may be trademarks of their respective owners.] * * If you do not wish to be bound by the terms of the GPL, an alternative * commercial license can be purchased. For details, please see visit the * Orson Charts home page: * * http://www.object-refinery.com/orsoncharts/index.html * */ package org.jfree.chart3d.plot; import java.util.EventListener; import org.jfree.chart3d.Chart3D; import org.jfree.chart3d.Chart3DChangeEvent; /** * An interface used to receive change events from {@link Plot3D} instances. * The {@link Chart3D} class will register with its plot to receive change * notifications - and upon receiving a change notification, it will pass it * on as a {@link Chart3DChangeEvent}. */ public interface Plot3DChangeListener extends EventListener { /** * Receives notification that a plot has changed. * * @param event event info. */ void plotChanged(Plot3DChangeEvent event); } orson-charts-2.1.0/src/main/java/org/jfree/chart3d/plot/StandardColorSource.java000066400000000000000000000122601417331271500275500ustar00rootroot00000000000000/* =========================================================== * Orson Charts : a 3D chart library for the Java(tm) platform * =========================================================== * * (C)opyright 2013-2022, by David Gilbert. All rights reserved. * * https://github.com/jfree/orson-charts * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . * * [Oracle and Java are registered trademarks of Oracle and/or its affiliates. * Other names may be trademarks of their respective owners.] * * If you do not wish to be bound by the terms of the GPL, an alternative * commercial license can be purchased. For details, please see visit the * Orson Charts home page: * * http://www.object-refinery.com/orsoncharts/index.html * */ package org.jfree.chart3d.plot; import java.awt.Color; import java.io.Serializable; import java.util.Arrays; import org.jfree.chart3d.internal.Args; import org.jfree.chart3d.Colors; import org.jfree.chart3d.data.DefaultKeyedValues; /** * A standard implementation of the {@link ColorSource} interface. *

* NOTE: This class is serializable, but the serialization format is subject * to change in future releases and should not be relied upon for persisting * instances of this class. */ @SuppressWarnings("serial") public final class StandardColorSource> implements ColorSource, Serializable { /** * An array of standard colors from which a color will be assigned if * there is not one already stored for a given key. */ private Color[] standardColors; /** Storage for the colors assigned to keys. */ private DefaultKeyedValues colors; /** * Creates a new instance with default colors. */ public StandardColorSource() { this(Colors.getDefaultColors()); } /** * Creates a new instance with the supplied sequence of colors. The * supplied array must have at least one entry, and all entries must be * non-{@code null}. * * @param colors the colors ({@code null} not permitted). */ public StandardColorSource(Color... colors) { Args.nullNotPermitted(colors, "colors"); if (colors.length == 0) { throw new IllegalArgumentException( "Zero length array not permitted."); } for (Color c: colors) { if (c == null) { throw new IllegalArgumentException( "Null array entries not permitted."); } } this.standardColors = colors.clone(); this.colors = new DefaultKeyedValues<>(); } /** * Returns the color associated with the specified key. * * @param key the key ({@code null} not permitted). * * @return The color (never {@code null}). */ @Override public Color getColor(K key) { // defer argument check Color c = this.colors.getValue(key); if (c != null) { return c; } c = this.standardColors[this.colors.getItemCount() % this.standardColors.length]; this.colors.put(key, c); return c; } /** * Sets the color for the specified key. * * @param key the key ({@code null} not permitted). * @param color the color ({@code null} permitted). */ @Override public void setColor(K key, Color color) { if (color != null) { this.colors.put(key, color); } else { this.colors.remove(key); } } /** * Clears existing color settings and sets the default colors to the * supplied value. This method is used by the framework and is not * normally called by client code. * * @param colors the colors ({@code null} not permitted). * * @since 1.2 */ @Override public void style(Color... colors) { this.standardColors = colors; this.colors.clear(); } /** * Tests this paint source for equality with an arbitrary object. * * @param obj the object ({@code null} permitted). * * @return A boolean. */ @Override public boolean equals(Object obj) { if (obj == this) { return true; } if (!(obj instanceof StandardColorSource)) { return false; } StandardColorSource that = (StandardColorSource) obj; if (!Arrays.equals(this.standardColors, that.standardColors)) { return false; } if (!this.colors.equals(that.colors)) { return false; } return true; } }orson-charts-2.1.0/src/main/java/org/jfree/chart3d/plot/StandardFontSource.java000066400000000000000000000117611417331271500274050ustar00rootroot00000000000000/* =========================================================== * Orson Charts : a 3D chart library for the Java(tm) platform * =========================================================== * * (C)opyright 2013-2022, by David Gilbert. All rights reserved. * * https://github.com/jfree/orson-charts * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . * * [Oracle and Java are registered trademarks of Oracle and/or its affiliates. * Other names may be trademarks of their respective owners.] * * If you do not wish to be bound by the terms of the GPL, an alternative * commercial license can be purchased. For details, please see visit the * Orson Charts home page: * * http://www.object-refinery.com/orsoncharts/index.html * */ package org.jfree.chart3d.plot; import java.awt.Font; import java.io.Serializable; import org.jfree.chart3d.data.DefaultKeyedValues; import org.jfree.chart3d.internal.Args; /** * A standard implementation of the {@link FontSource} interface. *

* NOTE: This class is serializable, but the serialization format is subject * to change in future releases and should not be relied upon for persisting * instances of this class. */ @SuppressWarnings("serial") public final class StandardFontSource> implements FontSource, Serializable { private static Font DEFAULT_FONT = new Font("Dialog", Font.PLAIN, 12); /** Storage for the fonts assigned to keys. */ private DefaultKeyedValues fonts; /** The default font (never {@code null}). */ private Font defaultFont; /** * Creates a new instance with default fonts. */ public StandardFontSource() { this(DEFAULT_FONT); } /** * Creates a new font source with the specified default font. * * @param defaultFont the default font ({@code null} not permitted). */ public StandardFontSource(Font defaultFont) { Args.nullNotPermitted(defaultFont, "defaultFont"); this.defaultFont = defaultFont; this.fonts = new DefaultKeyedValues<>(); } /** * Returns the default font. The default value is {@link #DEFAULT_FONT}. * * @return The default font (never {@code null}). */ public Font getDefaultFont() { return this.defaultFont; } /** * Sets the default font. * * @param font the font ({@code null} not permitted). */ public void setDefaultFont(Font font) { Args.nullNotPermitted(font, "font"); this.defaultFont = font; } /** * Returns the font for the specified key. * * @param key the key ({@code null} not permitted). * * @return The font (never {@code null}). */ @Override public Font getFont(K key) { Font result = this.fonts.getValue(key); if (result != null) { return result; } else { return this.defaultFont; } } /** * Sets the font associated with the specified key. * * @param key the key ({@code null} not permitted). * @param font the font ({@code null} permitted). */ @Override public void setFont(K key, Font font) { if (font != null) { this.fonts.put(key, font); } else { this.fonts.remove(key); } } /** * Clears existing font settings and sets the default font to the * supplied value. This method is used by the framework and is not * normally called by client code. * * @param font the font ({@code null} not permitted). * * @since 1.2 */ @Override public void style(Font font) { Args.nullNotPermitted(font, "font"); this.defaultFont = font; this.fonts.clear(); } /** * Tests this paint source for equality with an arbitrary object. * * @param obj the object ({@code null} permitted). * * @return A boolean. */ @Override public boolean equals(Object obj) { if (obj == this) { return true; } if (!(obj instanceof StandardFontSource)) { return false; } StandardFontSource that = (StandardFontSource) obj; if (!this.defaultFont.equals(that.defaultFont)) { return false; } if (!this.fonts.equals(that.fonts)) { return false; } return true; } }orson-charts-2.1.0/src/main/java/org/jfree/chart3d/plot/XYZPlot.java000066400000000000000000000612731417331271500251710ustar00rootroot00000000000000/* =========================================================== * Orson Charts : a 3D chart library for the Java(tm) platform * =========================================================== * * (C)opyright 2013-2022, by David Gilbert. All rights reserved. * * https://github.com/jfree/orson-charts * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . * * [Oracle and Java are registered trademarks of Oracle and/or its affiliates. * Other names may be trademarks of their respective owners.] * * If you do not wish to be bound by the terms of the GPL, an alternative * commercial license can be purchased. For details, please see visit the * Orson Charts home page: * * http://www.object-refinery.com/orsoncharts/index.html * */ package org.jfree.chart3d.plot; import java.awt.BasicStroke; import java.awt.Color; import java.awt.Paint; import java.awt.Stroke; import java.io.Serializable; import java.io.IOException; import java.io.ObjectInputStream; import java.io.ObjectOutputStream; import java.util.ArrayList; import java.util.List; import org.jfree.chart3d.internal.Args; import org.jfree.chart3d.ChartElementVisitor; import org.jfree.chart3d.axis.Axis3DChangeEvent; import org.jfree.chart3d.axis.Axis3DChangeListener; import org.jfree.chart3d.axis.ValueAxis3D; import org.jfree.chart3d.data.Dataset3DChangeEvent; import org.jfree.chart3d.data.Dataset3DChangeListener; import org.jfree.chart3d.data.ItemKey; import org.jfree.chart3d.data.xyz.XYZDataset; import org.jfree.chart3d.data.xyz.XYZItemKey; import org.jfree.chart3d.graphics3d.Dimension3D; import org.jfree.chart3d.graphics3d.World; import org.jfree.chart3d.internal.ObjectUtils; import org.jfree.chart3d.internal.SerialUtils; import org.jfree.chart3d.label.StandardXYZItemLabelGenerator; import org.jfree.chart3d.label.StandardXYZLabelGenerator; import org.jfree.chart3d.label.XYZItemLabelGenerator; import org.jfree.chart3d.label.XYZLabelGenerator; import org.jfree.chart3d.legend.LegendItemInfo; import org.jfree.chart3d.legend.StandardLegendItemInfo; import org.jfree.chart3d.renderer.ComposeType; import org.jfree.chart3d.renderer.Renderer3DChangeEvent; import org.jfree.chart3d.renderer.Renderer3DChangeListener; import org.jfree.chart3d.renderer.xyz.XYZRenderer; /** * A 3D plot with three numerical axes that displays data from an * {@link XYZDataset}. *

* NOTE: This class is serializable, but the serialization format is subject * to change in future releases and should not be relied upon for persisting * instances of this class. */ public class XYZPlot extends AbstractPlot3D implements Dataset3DChangeListener, Axis3DChangeListener, Renderer3DChangeListener, Serializable { private static final Stroke DEFAULT_GRIDLINE_STROKE = new BasicStroke(0.5f, BasicStroke.CAP_ROUND, BasicStroke.JOIN_ROUND, 1f, new float[] { 3f, 3f }, 0f); /** The dataset. */ private XYZDataset dataset; /** The renderer. */ private XYZRenderer renderer; /** The x-axis. */ private ValueAxis3D xAxis; /** The y-axis. */ private ValueAxis3D yAxis; /** The z-axis. */ private ValueAxis3D zAxis; /** Are gridlines visible for the x-axis? */ private boolean gridlinesVisibleX; /** The paint for the x-axis gridlines. */ private transient Paint gridlinePaintX; /** The stroke for the x-axis gridlines. */ private transient Stroke gridlineStrokeX; /** Are gridlines visible for the y-axis? */ private boolean gridlinesVisibleY; /** The paint for the y-axis gridlines. */ private transient Paint gridlinePaintY; /** The stroke for the y-axis gridlines. */ private transient Stroke gridlineStrokeY; /** Are gridlines visible for the z-axis? */ private boolean gridlinesVisibleZ; /** The paint for the z-axis gridlines. */ private transient Paint gridlinePaintZ; /** The stroke for the z-axis gridlines. */ private transient Stroke gridlineStrokeZ; /** The legend label generator. */ private XYZLabelGenerator legendLabelGenerator; /** The tool tip generator (if null there will be no tooltips). */ private XYZItemLabelGenerator toolTipGenerator; /** * Creates a new plot with the specified axes. * * @param dataset the dataset ({@code null} not permitted). * @param renderer the renderer ({@code null} not permitted). * @param xAxis the x-axis ({@code null} not permitted). * @param yAxis the y-axis ({@code null} not permitted). * @param zAxis the z-axis ({@code null} not permitted). */ public XYZPlot(XYZDataset dataset, XYZRenderer renderer, ValueAxis3D xAxis, ValueAxis3D yAxis, ValueAxis3D zAxis) { Args.nullNotPermitted(dataset, "dataset"); Args.nullNotPermitted(renderer, "renderer"); Args.nullNotPermitted(xAxis, "xAxis"); Args.nullNotPermitted(yAxis, "yAxis"); Args.nullNotPermitted(zAxis, "zAxis"); this.dimensions = new Dimension3D(10, 10, 10); this.dataset = dataset; this.dataset.addChangeListener(this); this.renderer = renderer; this.renderer.setPlot(this); this.renderer.addChangeListener(this); this.xAxis = xAxis; this.xAxis.addChangeListener(this); this.xAxis.configureAsXAxis(this); this.zAxis = zAxis; this.zAxis.addChangeListener(this); this.zAxis.configureAsZAxis(this); this.yAxis = yAxis; this.yAxis.addChangeListener(this); this.yAxis.configureAsYAxis(this); this.gridlinesVisibleX = true; this.gridlinePaintX = Color.WHITE; this.gridlineStrokeX = DEFAULT_GRIDLINE_STROKE; this.gridlinesVisibleY = true; this.gridlinePaintY = Color.WHITE; this.gridlineStrokeY = DEFAULT_GRIDLINE_STROKE; this.gridlinesVisibleZ = true; this.gridlinePaintZ = Color.WHITE; this.gridlineStrokeZ = DEFAULT_GRIDLINE_STROKE; this.legendLabelGenerator = new StandardXYZLabelGenerator(); this.toolTipGenerator = new StandardXYZItemLabelGenerator(); } /** * Sets the dimensions for the plot and notifies registered listeners that * the plot dimensions have been changed. * * @param dim the new dimensions ({@code null} not permitted). */ public void setDimensions(Dimension3D dim) { Args.nullNotPermitted(dim, "dim"); this.dimensions = dim; fireChangeEvent(true); } /** * Returns the dataset for the plot. * * @return The dataset (never {@code null}). */ public XYZDataset getDataset() { return this.dataset; } /** * Sets the dataset and sends a change event notification to all registered * listeners. * * @param dataset the new dataset ({@code null} not permitted). */ public void setDataset(XYZDataset dataset) { Args.nullNotPermitted(dataset, "dataset"); this.dataset.removeChangeListener(this); this.dataset = dataset; this.dataset.addChangeListener(this); fireChangeEvent(true); } /** * Returns the x-axis. * * @return The x-axis (never {@code null}). */ public ValueAxis3D getXAxis() { return this.xAxis; } /** * Sets the x-axis and sends a {@link Plot3DChangeEvent} to all registered * listeners. * * @param xAxis the x-axis ({@code null} not permitted). */ public void setXAxis(ValueAxis3D xAxis) { Args.nullNotPermitted(xAxis, "xAxis"); this.xAxis.removeChangeListener(this); xAxis.configureAsXAxis(this); xAxis.addChangeListener(this); this.xAxis = xAxis; fireChangeEvent(true); } /** * Returns the y-axis. * * @return The y-axis (never {@code null}). */ public ValueAxis3D getYAxis() { return this.yAxis; } /** * Sets the y-axis and sends a {@link Plot3DChangeEvent} to all registered * listeners. * * @param yAxis the y-axis ({@code null} not permitted). */ public void setYAxis(ValueAxis3D yAxis) { Args.nullNotPermitted(yAxis, "yAxis"); this.yAxis.removeChangeListener(this); yAxis.configureAsYAxis(this); yAxis.addChangeListener(this); this.yAxis = yAxis; fireChangeEvent(true); } /** * Returns the z-axis. * * @return The z-axis (never {@code null}). */ public ValueAxis3D getZAxis() { return this.zAxis; } /** * Sets the z-axis and sends a {@link Plot3DChangeEvent} to all registered * listeners. * * @param zAxis the z-axis ({@code null} not permitted). */ public void setZAxis(ValueAxis3D zAxis) { Args.nullNotPermitted(zAxis, "zAxis"); this.zAxis.removeChangeListener(this); zAxis.configureAsZAxis(this); zAxis.addChangeListener(this); this.zAxis = zAxis; fireChangeEvent(true); } /** * Returns the renderer for the plot. * * @return The renderer (possibly {@code null}). */ public XYZRenderer getRenderer() { return this.renderer; } /** * Sets the renderer for the plot and sends a {@link Plot3DChangeEvent} * to all registered listeners. * * @param renderer the renderer ({@code null} not permitted). */ public void setRenderer(XYZRenderer renderer) { this.renderer.setPlot(null); this.renderer.removeChangeListener(this); this.renderer = renderer; this.renderer.setPlot(this); this.renderer.addChangeListener(this); fireChangeEvent(true); } /** * Returns the flag that controls whether or not gridlines are shown for * the x-axis. * * @return A boolean. */ public boolean isGridlinesVisibleX() { return this.gridlinesVisibleX; } /** * Sets the flag that controls whether or not gridlines are shown for the * x-axis and sends a {@link Plot3DChangeEvent} to all registered * listeners. * * @param visible the new flag value. */ public void setGridlinesVisibleX(boolean visible) { this.gridlinesVisibleX = visible; fireChangeEvent(false); } /** * Returns the paint used to draw the gridlines for the x-axis. * * @return The paint ({@code null} not permitted). */ public Paint getGridlinePaintX() { return this.gridlinePaintX; } /** * Sets the paint used to draw the gridlines for the x-axis, and sends * a {@link Plot3DChangeEvent} to all registered listeners. * * @param paint the paint ({@code null} not permitted). */ public void setGridlinePaintX(Paint paint) { Args.nullNotPermitted(paint, "paint"); this.gridlinePaintX = paint; fireChangeEvent(false); } /** * Returns the stroke used to draw the gridlines for the x-axis. * * @return The stroke ({@code null} not permitted). */ public Stroke getGridlineStrokeX() { return this.gridlineStrokeX; } /** * Sets the stroke used to draw the gridlines for the x-axis, and sends * a {@link Plot3DChangeEvent} to all registered listeners. * * @param stroke the stroke ({@code null} not permitted). */ public void setGridlineStrokeX(Stroke stroke) { Args.nullNotPermitted(stroke, "stroke"); this.gridlineStrokeX = stroke; fireChangeEvent(false); } /** * Returns the flag that controls whether or not gridlines are shown for * the y-axis. * * @return A boolean. */ public boolean isGridlinesVisibleY() { return this.gridlinesVisibleY; } /** * Sets the flag that controls whether or not gridlines are shown for the * y-axis and sends a {@link Plot3DChangeEvent} to all registered * listeners. * * @param visible the new flag value. */ public void setGridlinesVisibleY(boolean visible) { this.gridlinesVisibleY = visible; fireChangeEvent(false); } /** * Returns the paint used to draw the gridlines for the y-axis. * * @return The paint ({@code null} not permitted). */ public Paint getGridlinePaintY() { return this.gridlinePaintY; } /** * Sets the paint used to draw the gridlines for the y-axis, and sends * a {@link Plot3DChangeEvent} to all registered listeners. * * @param paint the paint ({@code null} not permitted). */ public void setGridlinePaintY(Paint paint) { Args.nullNotPermitted(paint, "paint"); this.gridlinePaintY = paint; fireChangeEvent(false); } /** * Returns the stroke used to draw the gridlines for the y-axis. * * @return The stroke ({@code null} not permitted). */ public Stroke getGridlineStrokeY() { return this.gridlineStrokeY; } /** * Sets the stroke used to draw the gridlines for the y-axis, and sends * a {@link Plot3DChangeEvent} to all registered listeners. * * @param stroke the stroke ({@code null} not permitted). */ public void setGridlineStrokeY(Stroke stroke) { Args.nullNotPermitted(stroke, "stroke"); this.gridlineStrokeY = stroke; fireChangeEvent(false); } /** * Returns the flag that controls whether or not gridlines are shown for * the z-axis. * * @return A boolean. */ public boolean isGridlinesVisibleZ() { return this.gridlinesVisibleZ; } /** * Sets the flag that controls whether or not gridlines are shown for the * z-axis and sends a {@link Plot3DChangeEvent} to all registered * listeners. * * @param visible the new flag value. */ public void setGridlinesVisibleZ(boolean visible) { this.gridlinesVisibleZ = visible; fireChangeEvent(false); } /** * Returns the paint used to draw the gridlines for the z-axis. * * @return The paint ({@code null} not permitted). */ public Paint getGridlinePaintZ() { return this.gridlinePaintZ; } /** * Sets the paint used to draw the gridlines for the z-axis, and sends * a {@link Plot3DChangeEvent} to all registered listeners. * * @param paint the paint ({@code null} not permitted). */ public void setGridlinePaintZ(Paint paint) { Args.nullNotPermitted(paint, "paint"); this.gridlinePaintZ = paint; fireChangeEvent(false); } /** * Returns the stroke used to draw the gridlines for the z-axis. * * @return The stroke ({@code null} not permitted). */ public Stroke getGridlineStrokeZ() { return this.gridlineStrokeZ; } /** * Sets the stroke used to draw the gridlines for the z-axis, and sends * a {@link Plot3DChangeEvent} to all registered listeners. * * @param stroke the stroke ({@code null} not permitted). */ public void setGridlineStrokeZ(Stroke stroke) { Args.nullNotPermitted(stroke, "stroke"); this.gridlineStrokeZ = stroke; fireChangeEvent(false); } /** * Returns the legend label generator. The default value is a default * instance of {@link StandardXYZLabelGenerator}. * * @return The legend label generator (never {@code null}). * * @since 1.2 */ public XYZLabelGenerator getLegendLabelGenerator() { return this.legendLabelGenerator; } /** * Sets the legend label generator and sends a {@link Plot3DChangeEvent} * to all registered listeners. * * @param generator the generator ({@code null} not permitted). * * @since 1.2 */ public void setLegendLabelGenerator(XYZLabelGenerator generator) { Args.nullNotPermitted(generator, "generator"); this.legendLabelGenerator = generator; fireChangeEvent(false); } /** * Returns a list containing legend item info, typically one item for * each series in the chart. This is intended for use in the construction * of a chart legend. * * @return A list containing legend item info. */ @Override @SuppressWarnings("unchecked") // we don't know the generic types of the dataset public List getLegendInfo() { List result = new ArrayList<>(); List> keys = this.dataset.getSeriesKeys(); for (Comparable key : keys) { String label = this.legendLabelGenerator.generateSeriesLabel( this.dataset, key); int series = this.dataset.getSeriesIndex(key); Color color = this.renderer.getColorSource().getLegendColor(series); LegendItemInfo info = new StandardLegendItemInfo(key, label, color); result.add(info); } return result; } /** * Adds 3D objects representing the current data for the plot to the * specified world. After the world has been populated (or constructed) in * this way, it is ready for rendering. * * @param world the world ({@code null} not permitted). * @param xOffset the x-offset. * @param yOffset the y-offset. * @param zOffset the z-offset. */ @Override public void compose(World world, double xOffset, double yOffset, double zOffset) { if (this.renderer.getComposeType() == ComposeType.ALL) { this.renderer.composeAll(this, world, this.dimensions, xOffset, yOffset, zOffset); } else if (this.renderer.getComposeType() == ComposeType.PER_ITEM) { // for each data point in the dataset figure out if the composed // shape intersects with the visible // subset of the world, and if so add the object int seriesCount = this.dataset.getSeriesCount(); for (int series = 0; series < seriesCount; series++) { int itemCount = this.dataset.getItemCount(series); for (int item = 0; item < itemCount; item++) { this.renderer.composeItem(this.dataset, series, item, world, this.dimensions, xOffset, yOffset, zOffset); } } } else { // if we get here, someone changed the ComposeType enum throw new IllegalStateException("ComposeType not expected: " + this.renderer.getComposeType()); } } @Override public String generateToolTipText(ItemKey itemKey) { if (!(itemKey instanceof XYZItemKey)) { throw new IllegalArgumentException( "The itemKey must be a XYZItemKey instance."); } if (this.toolTipGenerator == null) { return null; } XYZItemKey k = (XYZItemKey) itemKey; return this.toolTipGenerator.generateItemLabel(dataset, k.getSeriesKey(), k.getItemIndex()); } /** * Receives a visitor. This is a general purpose mechanism, but the main * use is to apply chart style changes across all the elements of a * chart. * * @param visitor the visitor ({@code null} not permitted). * * @since 1.2 */ @Override public void receive(ChartElementVisitor visitor) { this.xAxis.receive(visitor); this.yAxis.receive(visitor); this.zAxis.receive(visitor); this.renderer.receive(visitor); visitor.visit(this); } /** * Tests this plot instance for equality with an arbitrary object. * * @param obj the object ({@code null} permitted). * * @return A boolean. */ @Override public boolean equals(Object obj) { if (obj == this) { return true; } if (!(obj instanceof XYZPlot)) { return false; } XYZPlot that = (XYZPlot) obj; if (!this.dimensions.equals(that.dimensions)) { return false; } if (this.gridlinesVisibleX != that.gridlinesVisibleX) { return false; } if (this.gridlinesVisibleY != that.gridlinesVisibleY) { return false; } if (this.gridlinesVisibleZ != that.gridlinesVisibleZ) { return false; } if (!ObjectUtils.equalsPaint(this.gridlinePaintX, that.gridlinePaintX)) { return false; } if (!ObjectUtils.equalsPaint(this.gridlinePaintY, that.gridlinePaintY)) { return false; } if (!ObjectUtils.equalsPaint(this.gridlinePaintZ, that.gridlinePaintZ)) { return false; } if (!this.gridlineStrokeX.equals(that.gridlineStrokeX)) { return false; } if (!this.gridlineStrokeY.equals(that.gridlineStrokeY)) { return false; } if (!this.gridlineStrokeZ.equals(that.gridlineStrokeZ)) { return false; } if (!this.legendLabelGenerator.equals(that.legendLabelGenerator)) { return false; } return super.equals(obj); } /** * Receives notification that one of the plot's axes has changed, and * responds by passing on a {@link Plot3DChangeEvent} to the plot's * registered listeners (with the default set-up, this notifies the * chart). * * @param event the event. */ @Override public void axisChanged(Axis3DChangeEvent event) { if (xAxis == event.getAxis()) { xAxis.configureAsXAxis(this); } else if (yAxis == event.getAxis()) { yAxis.configureAsYAxis(this); } else if (zAxis == event.getAxis()) { zAxis.configureAsZAxis(this); } fireChangeEvent(event.requiresWorldUpdate()); } /** * Receives notification that the plot's renderer has changed, and * responds by passing on a {@link Plot3DChangeEvent} to the plot's * registered listeners (with the default set-up, this notifies the * chart). * * @param event the event. */ @Override public void rendererChanged(Renderer3DChangeEvent event) { fireChangeEvent(event.requiresWorldUpdate()); } /** * Receives notification that the plot's dataset has changed, and * responds by passing on a {@link Plot3DChangeEvent} to the plot's * registered listeners (with the default set-up, this notifies the * chart). * * @param event the event. */ @Override public void datasetChanged(Dataset3DChangeEvent event) { this.xAxis.configureAsXAxis(this); this.yAxis.configureAsYAxis(this); this.zAxis.configureAsZAxis(this); super.datasetChanged(event); } /** * Provides serialization support. * * @param stream the output stream. * * @throws IOException if there is an I/O error. */ private void writeObject(ObjectOutputStream stream) throws IOException { stream.defaultWriteObject(); SerialUtils.writePaint(this.gridlinePaintX, stream); SerialUtils.writePaint(this.gridlinePaintY, stream); SerialUtils.writePaint(this.gridlinePaintZ, stream); SerialUtils.writeStroke(this.gridlineStrokeX, stream); SerialUtils.writeStroke(this.gridlineStrokeY, stream); SerialUtils.writeStroke(this.gridlineStrokeZ, stream); } /** * Provides serialization support. * * @param stream the input stream. * * @throws IOException if there is an I/O error. * @throws ClassNotFoundException if there is a classpath problem. */ private void readObject(ObjectInputStream stream) throws IOException, ClassNotFoundException { stream.defaultReadObject(); this.gridlinePaintX = SerialUtils.readPaint(stream); this.gridlinePaintY = SerialUtils.readPaint(stream); this.gridlinePaintZ = SerialUtils.readPaint(stream); this.gridlineStrokeX = SerialUtils.readStroke(stream); this.gridlineStrokeY = SerialUtils.readStroke(stream); this.gridlineStrokeZ = SerialUtils.readStroke(stream); } } orson-charts-2.1.0/src/main/java/org/jfree/chart3d/plot/package-info.java000066400000000000000000000004221417331271500261510ustar00rootroot00000000000000/** * Standard plot types ({@link org.jfree.chart3d.plot.PiePlot3D}, * {@link org.jfree.chart3d.plot.CategoryPlot3D} and * {@link org.jfree.chart3d.plot.XYZPlot}) that can be used with the * {@link org.jfree.chart3d.Chart3D} class. */ package org.jfree.chart3d.plot; orson-charts-2.1.0/src/main/java/org/jfree/chart3d/renderer/000077500000000000000000000000001417331271500236145ustar00rootroot00000000000000orson-charts-2.1.0/src/main/java/org/jfree/chart3d/renderer/AbstractColorScale.java000066400000000000000000000060651417331271500302000ustar00rootroot00000000000000/* =========================================================== * Orson Charts : a 3D chart library for the Java(tm) platform * =========================================================== * * (C)opyright 2013-2022, by David Gilbert. All rights reserved. * * https://github.com/jfree/orson-charts * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . * * [Oracle and Java are registered trademarks of Oracle and/or its affiliates. * Other names may be trademarks of their respective owners.] * * If you do not wish to be bound by the terms of the GPL, an alternative * commercial license can be purchased. For details, please see visit the * Orson Charts home page: * * http://www.object-refinery.com/orsoncharts/index.html * */ package org.jfree.chart3d.renderer; import java.io.Serializable; import org.jfree.chart3d.data.Range; import org.jfree.chart3d.internal.Args; /** * An abstract class from which a {@link ColorScale} implementation can be * derived. *

* NOTE: This class is serializable, but the serialization format is subject * to change in future releases and should not be relied upon for persisting * instances of this class. * * @since 1.1 */ @SuppressWarnings("serial") public abstract class AbstractColorScale implements Serializable { /** The data value range for the scale. */ private Range range; /** * Creates a new color scale for the specified data value range. * * @param range the data value range ({@code null} not permitted). */ protected AbstractColorScale(Range range) { Args.nullNotPermitted(range, "range"); this.range = range; } /** * Returns the range of data values over which the scale is defined. This * is specified via the constructor and once set cannot be changed. * * @return The range (never {@code null}). */ public Range getRange() { return this.range; } /** * Tests this color scale for equality with an arbitrary object. * * @param obj the object ({@code null} permitted). * * @return A boolean. */ @Override public boolean equals(Object obj) { if (obj == this) { return true; } if (!(obj instanceof AbstractColorScale)) { return false; } AbstractColorScale that = (AbstractColorScale) obj; if (!this.range.equals(that.range)) { return false; } return true; } } orson-charts-2.1.0/src/main/java/org/jfree/chart3d/renderer/AbstractRenderer3D.java000066400000000000000000000234251417331271500301060ustar00rootroot00000000000000/* =========================================================== * Orson Charts : a 3D chart library for the Java(tm) platform * =========================================================== * * (C)opyright 2013-2022, by David Gilbert. All rights reserved. * * https://github.com/jfree/orson-charts * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . * * [Oracle and Java are registered trademarks of Oracle and/or its affiliates. * Other names may be trademarks of their respective owners.] * * If you do not wish to be bound by the terms of the GPL, an alternative * commercial license can be purchased. For details, please see visit the * Orson Charts home page: * * http://www.object-refinery.com/orsoncharts/index.html * */ package org.jfree.chart3d.renderer; import java.awt.Color; import java.awt.Font; import java.io.Serializable; import javax.swing.event.EventListenerList; import org.jfree.chart3d.ChartElementVisitor; import org.jfree.chart3d.internal.Args; import org.jfree.chart3d.label.ItemLabelPositioning; /** * A base class for 3D renderers. */ public abstract class AbstractRenderer3D implements Renderer3D, Serializable { /** The font used to draw item labels. */ private Font itemLabelFont; /** The foreground color for item labels. */ private Color itemLabelColor; /** The background color for item labels. */ private Color itemLabelBackgroundColor; /** The item label positioning. */ private ItemLabelPositioning itemLabelPositioning; /** Storage for registered change listeners. */ private final transient EventListenerList listenerList; /** * A flag that controls whether or not the renderer will notify listeners * of changes (defaults to {@code true}, but sometimes it is useful * to disable this). */ private boolean notify; /** * Default constructor. */ protected AbstractRenderer3D() { this.itemLabelFont = new Font(Font.SERIF, Font.PLAIN, 12); this.itemLabelColor = Color.WHITE; this.itemLabelBackgroundColor = new Color(100, 100, 100, 100); //Renderer3D.TRANSPARENT_COLOR; this.itemLabelPositioning = ItemLabelPositioning.CENTRAL; this.listenerList = new EventListenerList(); this.notify = true; } /** * Returns the font used to display item labels, if there are any. * The default value is {@code Font(Font.SERIF, Font.PLAIN, 8)}. * * @return The font (never {@code null}). * * @since 1.3 */ public Font getItemLabelFont() { return itemLabelFont; } /** * Sets the font used to display item labels and sends a change event * to all registered listeners. * * @param itemLabelFont the font ({@code null} not permitted). * * @since 1.3 */ public void setItemLabelFont(Font itemLabelFont) { Args.nullNotPermitted(itemLabelFont, "itemLabelFont"); this.itemLabelFont = itemLabelFont; fireChangeEvent(true); } /** * Returns the foreground color used to display item labels. The default * value is {@code Color.BLACK}. * * @return The foreground color (never {@code null}). * * @since 1.3 */ public Color getItemLabelColor() { return itemLabelColor; } /** * Sets the foreground color used to display item labels and sends a * change event to all registered listeners. * * @param itemLabelColor the new color ({@code null} not permitted). * * @since 1.3 */ public void setItemLabelColor(Color itemLabelColor) { Args.nullNotPermitted(itemLabelColor, "itemLabelColor"); this.itemLabelColor = itemLabelColor; fireChangeEvent(true); } /** * Returns the background color for item labels. * * @return The background color (never {@code null}). * * @since 1.3 */ public Color getItemLabelBackgroundColor() { return itemLabelBackgroundColor; } /** * Sets the background color and sends a change event to all registered * listeners. * * @param color the new color ({@code null} not permitted). * * @since 1.3 */ public void setItemLabelBackgroundColor(Color color) { Args.nullNotPermitted(color, "color"); this.itemLabelBackgroundColor = color ; fireChangeEvent(true); } /** * Returns the item label positioning. The default value is * {@link ItemLabelPositioning#CENTRAL}. * * @return The item label positioning (never {@code null}). * * @since 1.3 */ public ItemLabelPositioning getItemLabelPositioning() { return itemLabelPositioning; } /** * Sets the item label positioning and sends a change event to all * registered listeners. * * @param positioning the new positioning ({@code null} not * permitted). * * @since 1.3 */ public void setItemLabelPositioning(ItemLabelPositioning positioning) { Args.nullNotPermitted(positioning, "positioning"); this.itemLabelPositioning = positioning; fireChangeEvent(true); } /** * Returns a flag that controls whether or not change events are sent to * registered listeners. * * @return A boolean. * * @see #setNotify(boolean) */ public boolean isNotify() { return this.notify; } /** * Sets a flag that controls whether or not listeners receive * {@link Renderer3DChangeEvent} notifications. * * @param notify a boolean. * * @see #isNotify() */ public void setNotify(boolean notify) { this.notify = notify; // if the flag is being set to true, there may be queued up changes... if (notify) { fireChangeEvent(true); } } /** * Receives a {@link ChartElementVisitor}. This is part of a general * purpose mechanism for traversing the chart structure and performing * operations on the elements in the structure. You won't normally call * this method directly. * * @param visitor the visitor ({@code null} not permitted). * * @since 1.2 */ @Override public void receive(ChartElementVisitor visitor) { visitor.visit(this); } /** * Registers an object for notification of changes to the renderer. * * @param listener the object to be registered. * * @see #removeChangeListener(Renderer3DChangeListener) */ @Override public void addChangeListener(Renderer3DChangeListener listener) { this.listenerList.add(Renderer3DChangeListener.class, listener); } /** * Unregisters an object for notification of changes to the renderer. * * @param listener the object to be unregistered. * * @see #addChangeListener(Renderer3DChangeListener) */ @Override public void removeChangeListener(Renderer3DChangeListener listener) { this.listenerList.remove(Renderer3DChangeListener.class, listener); } /** * Notifies all registered listeners that the plot has been modified. * * @param event information about the change event. */ public void notifyListeners(Renderer3DChangeEvent event) { // if the 'notify' flag has been switched to false, we don't notify // the listeners if (!this.notify) { return; } Object[] listeners = this.listenerList.getListenerList(); for (int i = listeners.length - 2; i >= 0; i -= 2) { if (listeners[i] == Renderer3DChangeListener.class) { ((Renderer3DChangeListener) listeners[i + 1]).rendererChanged( event); } } } /** * Sends a {@link Renderer3DChangeEvent} to all registered listeners. * * @param requiresWorldUpdate a flag indicating whether or not the change * requires the 3D world to be updated. */ protected void fireChangeEvent(boolean requiresWorldUpdate) { notifyListeners(new Renderer3DChangeEvent(this, requiresWorldUpdate)); } /** * Tests this renderer for equality with an arbitrary object. The * change listeners are NOT considered in the test, but the * {@code notify} flag is taken into account. * * @param obj the object ({@code null} permitted). * * @return A boolean. */ @Override public boolean equals(Object obj) { if (obj == this) { return true; } if (!(obj instanceof AbstractRenderer3D)) { return false; } AbstractRenderer3D that = (AbstractRenderer3D) obj; if (this.notify != that.notify) { return false; } if (!this.itemLabelFont.equals(that.itemLabelFont)) { return false; } if (!this.itemLabelColor.equals(that.itemLabelColor)) { return false; } if (!this.itemLabelBackgroundColor.equals( that.itemLabelBackgroundColor)) { return false; } if (this.itemLabelPositioning != that.itemLabelPositioning) { return false; } return true; } } orson-charts-2.1.0/src/main/java/org/jfree/chart3d/renderer/ColorScale.java000066400000000000000000000037151417331271500265130ustar00rootroot00000000000000/* =========================================================== * Orson Charts : a 3D chart library for the Java(tm) platform * =========================================================== * * (C)opyright 2013-2022, by David Gilbert. All rights reserved. * * https://github.com/jfree/orson-charts * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . * * [Oracle and Java are registered trademarks of Oracle and/or its affiliates. * Other names may be trademarks of their respective owners.] * * If you do not wish to be bound by the terms of the GPL, an alternative * commercial license can be purchased. For details, please see visit the * Orson Charts home page: * * http://www.object-refinery.com/orsoncharts/index.html * */ package org.jfree.chart3d.renderer; import java.awt.Color; import org.jfree.chart3d.data.Range; /** * A color scale converts a data value into a color according to some * predefined color scale. * * @since 1.1 */ public interface ColorScale { /** * Returns the range over which the scale is defined. * * @return The range (never {@code null}). */ Range getRange(); /** * Returns the color on the scale that corresponds to the specified * value. * * @param value the value. * * @return The color (never {@code null}). */ Color valueToColor(double value); } orson-charts-2.1.0/src/main/java/org/jfree/chart3d/renderer/ColorScaleRenderer.java000066400000000000000000000034621417331271500302010ustar00rootroot00000000000000/* =========================================================== * Orson Charts : a 3D chart library for the Java(tm) platform * =========================================================== * * (C)opyright 2013-2022, by David Gilbert. All rights reserved. * * https://github.com/jfree/orson-charts * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . * * [Oracle and Java are registered trademarks of Oracle and/or its affiliates. * Other names may be trademarks of their respective owners.] * * If you do not wish to be bound by the terms of the GPL, an alternative * commercial license can be purchased. For details, please see visit the * Orson Charts home page: * * http://www.object-refinery.com/orsoncharts/index.html * */ package org.jfree.chart3d.renderer; import org.jfree.chart3d.legend.ColorScaleLegendBuilder; /** * An interface that should be implemented by renderers that use a * {@link ColorScale} - this provides a mechanism for the * {@link ColorScaleLegendBuilder} to find the color scale. * * @since 1.1 */ public interface ColorScaleRenderer { /** * Returns the color scale used by the renderer. * * @return The color scale. */ ColorScale getColorScale(); } orson-charts-2.1.0/src/main/java/org/jfree/chart3d/renderer/ComposeType.java000066400000000000000000000040421417331271500267260ustar00rootroot00000000000000/* =========================================================== * Orson Charts : a 3D chart library for the Java(tm) platform * =========================================================== * * (C)opyright 2013-2022, by David Gilbert. All rights reserved. * * https://github.com/jfree/orson-charts * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . * * [Oracle and Java are registered trademarks of Oracle and/or its affiliates. * Other names may be trademarks of their respective owners.] * * If you do not wish to be bound by the terms of the GPL, an alternative * commercial license can be purchased. For details, please see visit the * Orson Charts home page: * * http://www.object-refinery.com/orsoncharts/index.html * */ package org.jfree.chart3d.renderer; import org.jfree.chart3d.renderer.xyz.SurfaceRenderer; /** * An enumeration of the different methods used by renderers for composing the * items in a chart. Most renderers work on a per-item basis, where the plot * iterates over the items in a dataset then asks the renderer to compose one * item at a time. An alternative approach is where the renderer does the * entire composition in one pass (the {@link SurfaceRenderer} does this, * since it plots a function rather than a dataset (performing sampling of * the function on-the-fly). */ public enum ComposeType { /** Compose each item individually. */ PER_ITEM, /** Compose all items at once. */ ALL } orson-charts-2.1.0/src/main/java/org/jfree/chart3d/renderer/FixedColorScale.java000066400000000000000000000072401417331271500274700ustar00rootroot00000000000000/* =========================================================== * Orson Charts : a 3D chart library for the Java(tm) platform * =========================================================== * * (C)opyright 2013-2022, by David Gilbert. All rights reserved. * * https://github.com/jfree/orson-charts * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . * * [Oracle and Java are registered trademarks of Oracle and/or its affiliates. * Other names may be trademarks of their respective owners.] * * If you do not wish to be bound by the terms of the GPL, an alternative * commercial license can be purchased. For details, please see visit the * Orson Charts home page: * * http://www.object-refinery.com/orsoncharts/index.html * */ package org.jfree.chart3d.renderer; import java.awt.Color; import java.io.Serializable; import org.jfree.chart3d.data.Range; import org.jfree.chart3d.internal.Args; import org.jfree.chart3d.renderer.xyz.SurfaceRenderer; /** * A {@link ColorScale} that returns the same color for every value on the * scale. This is used by the {@link SurfaceRenderer} when there is no need * to represent different value levels by color. *

* NOTE: This class is serializable, but the serialization format is subject * to change in future releases and should not be relied upon for persisting * instances of this class. * * @since 1.1 */ @SuppressWarnings("serial") public class FixedColorScale implements ColorScale, Serializable { /** The fixed color. */ private Color color; /** * The range (in fact this is here just to have something to return in the * getRange() method, it is not used by this implementation since we * always return the same color for all values). */ private Range range; /** * Creates a new {@code FixedColorScale} instance. * * @param color the color ({@code null} not permitted). */ public FixedColorScale(Color color) { Args.nullNotPermitted(color, "color"); this.color = color; this.range = new Range(0, 1); } /** * Returns the range {@code 0.0} to {@code 1.0} always. * * @return The range (never {@code null}). */ @Override public Range getRange() { return this.range; } /** * Returns a single color (as specified in the constructor) for all values. * * @param value the value. * * @return The fixed color. */ @Override public Color valueToColor(double value) { return this.color; } /** * Tests this instance for equality with an arbitrary object. * * @param obj the object ({@code null} permitted). * * @return A boolean. */ @Override public boolean equals(Object obj) { if (obj == this) { return true; } if (!(obj instanceof FixedColorScale)) { return false; } FixedColorScale that = (FixedColorScale) obj; if (!this.color.equals(that.color)) { return false; } return true; } } orson-charts-2.1.0/src/main/java/org/jfree/chart3d/renderer/GradientColorScale.java000066400000000000000000000122641417331271500301700ustar00rootroot00000000000000/* =========================================================== * Orson Charts : a 3D chart library for the Java(tm) platform * =========================================================== * * (C)opyright 2013-2022, by David Gilbert. All rights reserved. * * https://github.com/jfree/orson-charts * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . * * [Oracle and Java are registered trademarks of Oracle and/or its affiliates. * Other names may be trademarks of their respective owners.] * * If you do not wish to be bound by the terms of the GPL, an alternative * commercial license can be purchased. For details, please see visit the * Orson Charts home page: * * http://www.object-refinery.com/orsoncharts/index.html * */ package org.jfree.chart3d.renderer; import java.awt.Color; import org.jfree.chart3d.data.Range; import org.jfree.chart3d.internal.Args; /** * A color scale that runs a linear gradient between two colors. *

* NOTE: This class is serializable, but the serialization format is subject * to change in future releases and should not be relied upon for persisting * instances of this class. * * @since 1.1 */ @SuppressWarnings("serial") public class GradientColorScale extends AbstractColorScale implements ColorScale { /** The color at the low end of the value range. */ private final Color lowColor; /** The color at the high end of the value range. */ private final Color highColor; /** Storage for the color samples. */ private final Color[] colors; /** * Creates a new instance with the specified value range and colors. * * @param range the data value range ({@code null} not permitted). * @param lowColor the color for the low end of the data range * ({@code null} not permitted). * @param highColor the color for the high end of the data range * ({@code null} not permitted). */ public GradientColorScale(Range range, Color lowColor, Color highColor) { super(range); Args.nullNotPermitted(lowColor, "lowColor"); Args.nullNotPermitted(highColor, "highColor"); this.lowColor = lowColor; this.highColor = highColor; this.colors = new Color[255]; } /** * Returns the color for the low end of the data value range. * * @return The color (never {@code null}). */ public Color getLowColor() { return this.lowColor; } /** * Returns the color for the high end of the data value range. * * @return The color (never {@code null}). */ public Color getHighColor() { return this.highColor; } /** * Returns the number of samples used by this color scale. * * @return The number of samples. */ public int getSampleCount() { return this.colors.length; } /** * Returns the color corresponding to the specified data value. If this * * @param value the data value. * * @return The color (never {@code null}). */ @Override public Color valueToColor(double value) { Range r = getRange(); if (value < r.getMin()) { return valueToColor(r.getMin()); } if (value > r.getMax()) { return valueToColor(r.getMax()); } double fraction = getRange().percent(value); int i = Math.min((int) (fraction * this.colors.length), this.colors.length - 1); if (this.colors[i] == null) { float[] lrgba = this.lowColor.getRGBComponents(null); float[] hrgba = this.highColor.getRGBComponents(null); float p = (float) fraction; this.colors[i] = new Color(lrgba[0] * (1 - p) + hrgba[0] * p, lrgba[1] * (1 - p) + hrgba[1] * p, lrgba[2] * (1 - p) + hrgba[2] * p, lrgba[3] * (1 - p) + hrgba[3] * p); } return this.colors[i]; } /** * Tests this instance for equality with an arbitrary object. * * @param obj the object ({@code null} permitted). * * @return A boolean. */ @Override public boolean equals(Object obj) { if (obj == this) { return true; } if (!(obj instanceof GradientColorScale)) { return false; } GradientColorScale that = (GradientColorScale) obj; if (!this.lowColor.equals(that.lowColor)) { return false; } if (!this.highColor.equals(that.highColor)) { return false; } return super.equals(obj); } } orson-charts-2.1.0/src/main/java/org/jfree/chart3d/renderer/RainbowScale.java000066400000000000000000000130771417331271500270400ustar00rootroot00000000000000/* =========================================================== * Orson Charts : a 3D chart library for the Java(tm) platform * =========================================================== * * (C)opyright 2013-2022, by David Gilbert. All rights reserved. * * https://github.com/jfree/orson-charts * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . * * [Oracle and Java are registered trademarks of Oracle and/or its affiliates. * Other names may be trademarks of their respective owners.] * * If you do not wish to be bound by the terms of the GPL, an alternative * commercial license can be purchased. For details, please see visit the * Orson Charts home page: * * http://www.object-refinery.com/orsoncharts/index.html * */ package org.jfree.chart3d.renderer; import java.awt.Color; import org.jfree.chart3d.data.Range; import org.jfree.chart3d.internal.Args; /** * A color scale that returns all the colors of the rainbow. Instances of * this class are immutable and serializable. *

* NOTE: This class is serializable, but the serialization format is subject * to change in future releases and should not be relied upon for persisting * instances of this class. * * @since 1.1 */ @SuppressWarnings("serial") public class RainbowScale extends AbstractColorScale implements ColorScale { /** * A range to include all hues. This can be used for the * {@code hueSubrange} argument in the constructor. */ public static final Range ALL_HUES = new Range(0.0, 1.0); /** * A hue subrange that restricts colors to the blue to red range. This can * be used for the {@code hueSubrange} argument in the constructor. */ public static final Range BLUE_TO_RED_RANGE = new Range(0.0, 0.6666); /** Storage for the color samples. */ private Color[] colors; /** * The subrange of hues (useful to restrict the scale to the range from * blue to red, which is common in charts). */ private Range hueSubrange; /** * Creates a new rainbow scale for the specified value range, with 256 * color samples in the blue to red range. * * @param range the range ({@code null} not permitted). */ public RainbowScale(Range range) { this(range, 256, BLUE_TO_RED_RANGE); } /** * Creates a new rainbow scale for the specified value range, with the * given number of samples and hues restricted to the specified range. * * @param range the range ({@code null} not permitted). * @param samples the number of samples. * @param hueSubrange the hue sub-range. */ public RainbowScale(Range range, int samples, Range hueSubrange) { super(range); Args.nullNotPermitted(hueSubrange, "hueSubrange"); this.colors = new Color[samples]; this.hueSubrange = hueSubrange; } /** * Returns the number of samples used by this color scale. * * @return The number of samples. */ public int getSampleCount() { return this.colors.length; } /** * Returns the sub-range of hues used in this scale. * * @return The sub-range of hues. */ public Range getHueSubrange() { return this.hueSubrange; } /** * Converts a value to a color on the scale. * * @param value the value. * * @return A color (never {@code null}). */ @Override public Color valueToColor(double value) { Range r = getRange(); if (value < r.getMin()) { return valueToColor(r.getMin()); } if (value > r.getMax()) { return valueToColor(r.getMax()); } double fraction = getRange().percent(value); int i = (int) (fraction * (this.colors.length - 1)); if (this.colors[i] == null) { this.colors[i] = createRainbowColor(fraction); } return this.colors[i]; } /** * Creates the rainbow color corresponding to the specified fraction along * the scale range. * * @param fraction the fraction (0.0 to 1.0). * * @return The color. */ private Color createRainbowColor(double fraction) { double inv = 1.0 - fraction; double hue = this.hueSubrange.value(inv); return Color.getHSBColor((float) hue, 1.0f, 1.0f); } /** * Tests this color scale for equality with an arbitrary object. * * @param obj the object ({@code null} permitted). * * @return A boolean. */ @Override public boolean equals(Object obj) { if (obj == this) { return true; } if (!(obj instanceof RainbowScale)) { return false; } RainbowScale that = (RainbowScale) obj; if (this.colors.length != that.colors.length) { return false; } if (!this.hueSubrange.equals(that.hueSubrange)) { return false; } return super.equals(obj); } } orson-charts-2.1.0/src/main/java/org/jfree/chart3d/renderer/Renderer3D.java000066400000000000000000000061161417331271500264200ustar00rootroot00000000000000/* =========================================================== * Orson Charts : a 3D chart library for the Java(tm) platform * =========================================================== * * (C)opyright 2013-2022, by David Gilbert. All rights reserved. * * https://github.com/jfree/orson-charts * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . * * [Oracle and Java are registered trademarks of Oracle and/or its affiliates. * Other names may be trademarks of their respective owners.] * * If you do not wish to be bound by the terms of the GPL, an alternative * commercial license can be purchased. For details, please see visit the * Orson Charts home page: * * http://www.object-refinery.com/orsoncharts/index.html * */ package org.jfree.chart3d.renderer; import java.awt.Color; import org.jfree.chart3d.Chart3D; import org.jfree.chart3d.ChartElement; import org.jfree.chart3d.plot.CategoryPlot3D; import org.jfree.chart3d.plot.XYZPlot; /** * A renderer is an object responsible for constructing objects in a 3D model * that correspond to data items in a dataset. The renderer's methods will be * called by the plot ({@link CategoryPlot3D} or {@link XYZPlot}) that it is * assigned to. *

* All renderers support a change listener mechanism so that registered * listeners can be notified whenever any attribute of the renderer is modified. * Typically the plot that the renderer is assigned to will listen for * change events, and pass these events along to the {@link Chart3D} object. *

* Renderers should implement the {@code java.io.Serializable} interface, * so that charts can be serialized and deserialized, but this is not a forced * requirement (if you never use serialization, it won't matter if you * implement a renderer that does not support it). */ public interface Renderer3D extends ChartElement { /** * A color instance that is completely transparent. * * @since 1.3 */ Color TRANSPARENT_COLOR = new Color(0, 0, 0, 0); /** * Registers a listener to receive notification of changes to the * renderer. * * @param listener the listener ({@code null} not permitted). */ void addChangeListener(Renderer3DChangeListener listener); /** * Deregisters a listener so that it no longer receives notification of * changes to the renderer. * * @param listener the listener ({@code null} not permitted). */ void removeChangeListener(Renderer3DChangeListener listener); } orson-charts-2.1.0/src/main/java/org/jfree/chart3d/renderer/Renderer3DChangeEvent.java000066400000000000000000000067021417331271500305310ustar00rootroot00000000000000/* =========================================================== * Orson Charts : a 3D chart library for the Java(tm) platform * =========================================================== * * (C)opyright 2013-2022, by David Gilbert. All rights reserved. * * https://github.com/jfree/orson-charts * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . * * [Oracle and Java are registered trademarks of Oracle and/or its affiliates. * Other names may be trademarks of their respective owners.] * * If you do not wish to be bound by the terms of the GPL, an alternative * commercial license can be purchased. For details, please see visit the * Orson Charts home page: * * http://www.object-refinery.com/orsoncharts/index.html * */ package org.jfree.chart3d.renderer; import java.util.EventObject; /** * An event containing information about a change to a {@link Renderer3D}. * Any object that implements the {@link Renderer3DChangeListener} interface * can register with a renderer to receive change event notifications. By * default, the plot classes register with the renderer they manage in order * to monitor changes to the renderer. *

* NOTE: This class is serializable, but the serialization format is subject * to change in future releases and should not be relied upon for persisting * instances of this class. */ @SuppressWarnings("serial") public class Renderer3DChangeEvent extends EventObject { private Renderer3D renderer; private boolean requiresWorldUpdate; /** * Creates a new change event. * * @param renderer the renderer that changed ({@code null} not permitted). * @param requiresWorldUpdate a flag indicating whether or not the change * requires the 3D world to be updated. */ public Renderer3DChangeEvent(Renderer3D renderer, boolean requiresWorldUpdate) { this(renderer, renderer, requiresWorldUpdate); } /** * Creates a new change event. * * @param source the source. * @param renderer the renderer. * @param requiresWorldUpdate a flag indicating whether or not the change * requires the 3D world to be updated. */ public Renderer3DChangeEvent(Object source, Renderer3D renderer, boolean requiresWorldUpdate) { super(source); this.renderer = renderer; this.requiresWorldUpdate = requiresWorldUpdate; } /** * Returns the renderer that the event relates to. * * @return The renderer. */ public Renderer3D getRenderer() { return this.renderer; } /** * Returns the flag that indicates whether or not this change will require * the 3D world to be updated. * * @return A boolean. * * @since 1.2 */ public boolean requiresWorldUpdate() { return this.requiresWorldUpdate; } } orson-charts-2.1.0/src/main/java/org/jfree/chart3d/renderer/Renderer3DChangeListener.java000066400000000000000000000040211417331271500312250ustar00rootroot00000000000000/* =========================================================== * Orson Charts : a 3D chart library for the Java(tm) platform * =========================================================== * * (C)opyright 2013-2022, by David Gilbert. All rights reserved. * * https://github.com/jfree/orson-charts * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . * * [Oracle and Java are registered trademarks of Oracle and/or its affiliates. * Other names may be trademarks of their respective owners.] * * If you do not wish to be bound by the terms of the GPL, an alternative * commercial license can be purchased. For details, please see visit the * Orson Charts home page: * * http://www.object-refinery.com/orsoncharts/index.html * */ package org.jfree.chart3d.renderer; import java.util.EventListener; import org.jfree.chart3d.plot.CategoryPlot3D; import org.jfree.chart3d.plot.XYZPlot; /** * An interface through which notification of changes to a {@link Renderer3D} * can be received. By default, a {@link CategoryPlot3D} or an {@link XYZPlot} * will register as a listener on the renderer that it is using (if the * renderer changes, the plot passes on a change event to the chart). */ public interface Renderer3DChangeListener extends EventListener { /** * Called to signal a change to a renderer. * * @param event information about the change. */ void rendererChanged(Renderer3DChangeEvent event); } orson-charts-2.1.0/src/main/java/org/jfree/chart3d/renderer/category/000077500000000000000000000000001417331271500254315ustar00rootroot00000000000000orson-charts-2.1.0/src/main/java/org/jfree/chart3d/renderer/category/AbstractCategoryRenderer3D.java000066400000000000000000000165421417331271500334230ustar00rootroot00000000000000/* =========================================================== * Orson Charts : a 3D chart library for the Java(tm) platform * =========================================================== * * (C)opyright 2013-2022, by David Gilbert. All rights reserved. * * https://github.com/jfree/orson-charts * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . * * [Oracle and Java are registered trademarks of Oracle and/or its affiliates. * Other names may be trademarks of their respective owners.] * * If you do not wish to be bound by the terms of the GPL, an alternative * commercial license can be purchased. For details, please see visit the * Orson Charts home page: * * http://www.object-refinery.com/orsoncharts/index.html * */ package org.jfree.chart3d.renderer.category; import java.awt.Color; import java.io.Serializable; import org.jfree.chart3d.internal.Args; import org.jfree.chart3d.data.DataUtils; import org.jfree.chart3d.data.Range; import org.jfree.chart3d.data.Values3D; import org.jfree.chart3d.graphics3d.Offset3D; import org.jfree.chart3d.internal.ObjectUtils; import org.jfree.chart3d.label.CategoryItemLabelGenerator; import org.jfree.chart3d.plot.CategoryPlot3D; import org.jfree.chart3d.renderer.AbstractRenderer3D; import org.jfree.chart3d.renderer.Renderer3DChangeEvent; /** * A base class that can be used to implement renderers for a * {@link CategoryPlot3D}. */ public abstract class AbstractCategoryRenderer3D extends AbstractRenderer3D implements CategoryRenderer3D, Serializable { /** A reference to the plot that the renderer is currently assigned to. */ private CategoryPlot3D plot; /** * The color source is used to determine the color for each item drawn * by the renderer (never {@code null}). */ private CategoryColorSource colorSource; /** * An object that generates item labels for the chart. Can be null. */ private CategoryItemLabelGenerator itemLabelGenerator; /** The item label offsets. */ private Offset3D itemLabelOffsets; /** * Default constructor. */ public AbstractCategoryRenderer3D() { this.colorSource = new StandardCategoryColorSource(); this.itemLabelGenerator = null; this.itemLabelOffsets = new Offset3D(0.0, 0.05, 1.1); } /** * Returns the plot that the renderer is currently assigned to, if any. * * @return The plot or {@code null}. */ @Override public CategoryPlot3D getPlot() { return this.plot; } /** * Sets the plot that the renderer is assigned to. You do not need to * call this method yourself, the plot takes care of it when you call * the {@code setRenderer()} method on the plot. * * @param plot the plot ({@code null} permitted). */ @Override public void setPlot(CategoryPlot3D plot) { this.plot = plot; } /** * Returns the color source for the renderer. This is used to determine * the colors used for individual items in the chart, and the color to * display for a series in the chart legend. * * @return The color source (never {@code null}). */ @Override public CategoryColorSource getColorSource() { return this.colorSource; } /** * Sets the color source for the renderer and sends a * {@link Renderer3DChangeEvent} to all registered listeners. * * @param colorSource the color source ({@code null} not permitted). */ @Override public void setColorSource(CategoryColorSource colorSource) { Args.nullNotPermitted(colorSource, "colorSource"); this.colorSource = colorSource; fireChangeEvent(true); } /** * Sets a new color source for the renderer using the specified colors and * sends a {@link Renderer3DChangeEvent} to all registered listeners. This * is a convenience method that is equivalent to * {@code setColorSource(new StandardCategoryColorSource(colors))}. * * @param colors one or more colors ({@code null} not permitted). * * @since 1.1 */ @Override public void setColors(Color... colors) { setColorSource(new StandardCategoryColorSource(colors)); } /** * Returns the item label generator for the renderer (possibly * {@code null}). * * @return The item label generator (possibly {@code null}). * * @since 1.3 */ public CategoryItemLabelGenerator getItemLabelGenerator() { return itemLabelGenerator; } /** * Sets the item label generator for the renderer and sends a change event * to all registered listeners. * * @param generator the generator ({@code null} permitted). * * @since 1.3 */ public void setItemLabelGenerator(CategoryItemLabelGenerator generator) { this.itemLabelGenerator = generator; fireChangeEvent(true); } /** * Returns the item label offsets. * * @return The item label offsets (never {@code null}). * * @since 1.3 */ public Offset3D getItemLabelOffsets() { return this.itemLabelOffsets; } /** * Sets the item label offsets and sends a change event to all registered * listeners. * * @param offsets the offsets ({@code null} not permitted). * * @since 1.3 */ public void setItemLabelOffsets(Offset3D offsets) { Args.nullNotPermitted(offsets, "offsets"); this.itemLabelOffsets = offsets; fireChangeEvent(true); } /** * Returns the range of values that will be required on the value axis * to see all the data from the dataset. * * @param data the data ({@code null} not permitted). * * @return The range (possibly {@code null}) */ @Override public Range findValueRange(Values3D data) { return DataUtils.findValueRange(data); } /** * Tests this renderer for equality with an arbitrary object. * * @param obj the object ({@code null} permitted). * * @return A boolean. */ @Override public boolean equals(Object obj) { if (obj == this) { return true; } if (!(obj instanceof AbstractCategoryRenderer3D)) { return false; } AbstractCategoryRenderer3D that = (AbstractCategoryRenderer3D) obj; if (!this.colorSource.equals(that.colorSource)) { return false; } if (!ObjectUtils.equals(this.itemLabelGenerator, that.itemLabelGenerator)) { return false; } if (!this.itemLabelOffsets.equals(that.itemLabelOffsets)) { return false; } return super.equals(obj); } } orson-charts-2.1.0/src/main/java/org/jfree/chart3d/renderer/category/AreaRenderer3D.java000066400000000000000000001016161417331271500310270ustar00rootroot00000000000000/* =========================================================== * Orson Charts : a 3D chart library for the Java(tm) platform * =========================================================== * * (C)opyright 2013-2022, by David Gilbert. All rights reserved. * * https://github.com/jfree/orson-charts * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . * * [Oracle and Java are registered trademarks of Oracle and/or its affiliates. * Other names may be trademarks of their respective owners.] * * If you do not wish to be bound by the terms of the GPL, an alternative * commercial license can be purchased. For details, please see visit the * Orson Charts home page: * * http://www.object-refinery.com/orsoncharts/index.html * */ package org.jfree.chart3d.renderer.category; import java.awt.Color; import java.io.Serializable; import java.util.ArrayList; import java.util.List; import org.jfree.chart3d.Chart3DFactory; import org.jfree.chart3d.axis.CategoryAxis3D; import org.jfree.chart3d.axis.ValueAxis3D; import org.jfree.chart3d.data.DataUtils; import org.jfree.chart3d.data.KeyedValues3DItemKey; import org.jfree.chart3d.data.Range; import org.jfree.chart3d.data.Values3D; import org.jfree.chart3d.data.category.CategoryDataset3D; import org.jfree.chart3d.graphics3d.Dimension3D; import org.jfree.chart3d.graphics3d.Object3D; import org.jfree.chart3d.graphics3d.Offset3D; import org.jfree.chart3d.graphics3d.World; import org.jfree.chart3d.graphics3d.internal.Utils2D; import org.jfree.chart3d.internal.ObjectUtils; import org.jfree.chart3d.label.ItemLabelPositioning; import org.jfree.chart3d.plot.CategoryPlot3D; import org.jfree.chart3d.renderer.Renderer3DChangeEvent; /** * A renderer for creating 3D area charts from data in a * {@link CategoryDataset3D} (for use with a {@link CategoryPlot3D}). For * example: *

* image/AreaChart3DDemo1.svg *
* (refer to {@code AreaChart3DDemo1.java} for the code to generate the * above chart). *

* There is a factory method to create a chart using this renderer - see * {@link Chart3DFactory#createAreaChart(String, String, CategoryDataset3D, * String, String, String)}. *

* NOTE: This class is serializable, but the serialization format is subject * to change in future releases and should not be relied upon for persisting * instances of this class. */ @SuppressWarnings("serial") public class AreaRenderer3D extends AbstractCategoryRenderer3D implements Serializable { /** The base for the areas (defaults to 0.0). */ private double base; /** * The color used to paint the underside of the area object (if * {@code null}, the regular series color is used). */ private Color baseColor; /** The depth of the area. */ private double depth; /** * For isolated data values this attribute controls the width (x-axis) of * the box representing the data item, it is expressed as a percentage of * the category width. */ private double isolatedItemWidthPercent; /** * The color source that determines the color used to highlight clipped * items in the chart. */ private CategoryColorSource clipColorSource; /** * A flag that controls whether or not outlines are drawn for the faces * making up the area segments. */ private boolean drawFaceOutlines; /** * Default constructor. */ public AreaRenderer3D() { this.base = 0.0; this.baseColor = null; this.depth = 0.6; this.isolatedItemWidthPercent = 0.25; this.clipColorSource = new StandardCategoryColorSource(Color.RED); this.drawFaceOutlines = true; } /** * Returns the y-value for the base of the area. The default value is * {@code 0.0}. * * @return The base value. */ public double getBase() { return this.base; } /** * Sets the base value and sends a change event to all registered listeners. * * @param base the base value. */ public void setBase(double base) { this.base = base; fireChangeEvent(true); } /** * Returns the color used to paint the underside of the area polygons. * The default value is {@code null} (which means the undersides are * painted using the regular series color). * * @return The color (possibly {@code null}). * * @see #setBaseColor(java.awt.Color) */ public Color getBaseColor() { return this.baseColor; } /** * Sets the color for the underside of the area shapes and sends a * change event to all registered listeners. If you set * this to {@code null} the base will be painted with the regular * series color. * * @param color the color ({@code null} permitted). */ public void setBaseColor(Color color) { this.baseColor = color; fireChangeEvent(true); } /** * Returns the depth (in 3D) for the area (in world units). The * default value is {@code 0.6}. * * @return The depth. */ public double getDepth() { return this.depth; } /** * Sets the depth (in 3D) and sends a change event to all registered * listeners. * * @param depth the depth. */ public void setDepth(double depth) { this.depth = depth; fireChangeEvent(true); } /** * Returns the color source used to determine the color used to highlight * clipping in the chart elements. If the source is {@code null}, * then the regular series color is used instead. * * @return The color source (possibly {@code null}). * * @since 1.3 */ public CategoryColorSource getClipColorSource() { return this.clipColorSource; } /** * Sets the color source that determines the color used to highlight * clipping in the chart elements, and sends a {@link Renderer3DChangeEvent} * to all registered listeners. * * @param source the source ({@code null} permitted). * * @since 1.3 */ public void setClipColorSource(CategoryColorSource source) { this.clipColorSource = source; fireChangeEvent(true); } /** * Returns the flag that controls whether or not the faces making up area * segments will be drawn with outlines. The default value is * {@code true}. When anti-aliasing is on, the fill area for the * faces will have some gray shades around the edges, and these will show * up on the chart as thin lines (usually not visible if you turn off * anti-aliasing). To mask this, the rendering engine can draw an outline * around each face in the same color (this usually results in cleaner * output, but it is slower and can introduce some minor visual artifacts * as well depending on the output target). * * @return A boolean. * * @since 1.3 */ public boolean getDrawFaceOutlines() { return this.drawFaceOutlines; } /** * Sets the flag that controls whether or not outlines are drawn for the * faces making up the area segments and sends a change event to all * registered listeners. * * @param outline the new flag value. * * @since 1.3 */ public void setDrawFaceOutlines(boolean outline) { this.drawFaceOutlines = outline; fireChangeEvent(true); } /** * Returns the range (for the value axis) that is required for this * renderer to show all the values in the specified data set. This method * is overridden to ensure that the range includes the base value (normally * 0.0) set for the renderer. * * @param data the data ({@code null} not permitted). * * @return The range. */ @Override public Range findValueRange(Values3D data) { return DataUtils.findValueRange(data, this.base); } /** * Constructs and places one item from the specified dataset into the given * world. This method will be called by the {@link CategoryPlot3D} class * while iterating over the items in the dataset. * * @param dataset the dataset ({@code null} not permitted). * @param series the series index. * @param row the row index. * @param column the column index. * @param world the world ({@code null} not permitted). * @param dimensions the plot dimensions ({@code null} not permitted). * @param xOffset the x-offset. * @param yOffset the y-offset. * @param zOffset the z-offset. */ @Override @SuppressWarnings("unchecked") public void composeItem(CategoryDataset3D dataset, int series, int row, int column, World world, Dimension3D dimensions, double xOffset, double yOffset, double zOffset) { Number y = (Number) dataset.getValue(series, row, column); Number yprev = null; if (column > 0) { yprev = (Number) dataset.getValue(series, row, column - 1); } Number ynext = null; if (column < dataset.getColumnCount() - 1) { ynext = (Number) dataset.getValue(series, row, column + 1); } CategoryPlot3D plot = getPlot(); CategoryAxis3D rowAxis = plot.getRowAxis(); CategoryAxis3D columnAxis = plot.getColumnAxis(); ValueAxis3D valueAxis = plot.getValueAxis(); Range r = valueAxis.getRange(); Comparable seriesKey = dataset.getSeriesKey(series); Comparable rowKey = dataset.getRowKey(row); Comparable columnKey = dataset.getColumnKey(column); double rowValue = rowAxis.getCategoryValue(rowKey); double columnValue = columnAxis.getCategoryValue(columnKey); double ww = dimensions.getWidth(); double hh = dimensions.getHeight(); double dd = dimensions.getDepth(); // for any data value, we'll try to create two area segments, one to // the left of the value and one to the right of the value (each // halfway to the adjacent data value). If the adjacent data values // are null (or don't exist, as in the case of the first and last data // items), then we can create an isolated segment to represent the data // item. The final consideration is whether the opening and closing // faces of each segment are filled or not (if the segment connects to // another segment, there is no need to fill the end face) boolean createLeftSegment, createRightSegment, createIsolatedSegment; boolean leftOpen = false; boolean leftClose = false; boolean rightOpen = false; boolean rightClose = false; // for the first column there is no left segment, we also handle the // special case where there is just one column of data in which case // the renderer can only show an isolated data value if (column == 0) { createLeftSegment = false; // never for first item if (dataset.getColumnCount() == 1) { createRightSegment = false; createIsolatedSegment = (y != null); } else { createRightSegment = (y != null && ynext != null); rightOpen = true; rightClose = false; createIsolatedSegment = (y != null && ynext == null); } } // for the last column there is no right segment else if (column == dataset.getColumnCount() - 1) { // last column createRightSegment = false; // never for the last item createLeftSegment = (y != null && yprev != null); leftOpen = false; leftClose = true; createIsolatedSegment = (y != null && yprev == null); } // for the general case we handle left and right segments or an // isolated segment if the surrounding data values are null else { createLeftSegment = (y != null && yprev != null); leftOpen = false; leftClose = (createLeftSegment && ynext == null); createRightSegment = (y != null && ynext != null); rightOpen = (createRightSegment && yprev == null); rightClose = false; createIsolatedSegment = (y != null && yprev == null && ynext == null); } // now that we know what we have to create, we'll need some info // for the construction...world coordinates are required double xw = columnAxis.translateToWorld(columnValue, ww) + xOffset; double yw = Double.NaN; if (y != null) { yw = valueAxis.translateToWorld(y.doubleValue(), hh) + yOffset; } double zw = rowAxis.translateToWorld(rowValue, dd) + zOffset; double ywmin = valueAxis.translateToWorld(r.getMin(), hh) + yOffset; double ywmax = valueAxis.translateToWorld(r.getMax(), hh) + yOffset; double basew = valueAxis.translateToWorld(this.base, hh) + yOffset; Color color = getColorSource().getColor(series, row, column); Color clipColor = color; if (getClipColorSource() != null) { Color c = getClipColorSource().getColor(series, row, column); if (c != null) { clipColor = c; } } KeyedValues3DItemKey itemKey = new KeyedValues3DItemKey(seriesKey, rowKey, columnKey); if (createLeftSegment) { Comparable prevColumnKey = dataset.getColumnKey(column - 1); double prevColumnValue = columnAxis.getCategoryValue(prevColumnKey); double prevColumnX = columnAxis.translateToWorld(prevColumnValue, ww) + xOffset; double xl = (prevColumnX + xw) / 2.0; assert yprev != null; // we know this because createLeftSegment is // not 'true' otherwise double yprevw = valueAxis.translateToWorld(yprev.doubleValue(), hh) + yOffset; double yl = (yprevw + yw) / 2.0; List leftObjs = createSegment(xl, yl, xw, yw, zw, basew, ywmin, ywmax, color, this.baseColor, clipColor, leftOpen, leftClose); for (Object3D obj : leftObjs) { obj.setProperty(Object3D.ITEM_KEY, itemKey); obj.setOutline(this.drawFaceOutlines); world.add(obj); } } if (createRightSegment) { Comparable nextColumnKey = dataset.getColumnKey(column + 1); double nextColumnValue = columnAxis.getCategoryValue(nextColumnKey); double nextColumnX = columnAxis.translateToWorld(nextColumnValue, ww) + xOffset; double xr = (nextColumnX + xw) / 2.0; assert ynext != null; // we know this because createRightSegment is // not 'true' otherwise double ynextw = valueAxis.translateToWorld(ynext.doubleValue(), hh) + yOffset; double yr = (ynextw + yw) / 2.0; List rightObjs = createSegment(xw, yw, xr, yr, zw, basew, ywmin, ywmax, color, this.baseColor, clipColor, rightOpen, rightClose); for (Object3D obj : rightObjs) { obj.setProperty(Object3D.ITEM_KEY, itemKey); obj.setOutline(this.drawFaceOutlines); world.add(obj); } } if (createIsolatedSegment) { double cw = columnAxis.getCategoryWidth() * this.isolatedItemWidthPercent; double cww = columnAxis.translateToWorld(cw, ww); double h = yw - basew; Object3D isolated = Object3D.createBox(xw, cww, yw - h / 2, h, zw, this.depth, color); isolated.setOutline(this.drawFaceOutlines); isolated.setProperty(Object3D.ITEM_KEY, itemKey); world.add(isolated); } if (getItemLabelGenerator() != null && !Double.isNaN(yw) && yw >= ywmin && yw <= ywmax) { String label = getItemLabelGenerator().generateItemLabel(dataset, seriesKey, rowKey, columnKey); ItemLabelPositioning positioning = getItemLabelPositioning(); Offset3D offsets = getItemLabelOffsets(); double ydelta = dimensions.getHeight() * offsets.getDY(); if (yw < basew) { ydelta = -ydelta; } if (positioning.equals(ItemLabelPositioning.CENTRAL)) { Object3D labelObj = Object3D.createLabelObject(label, getItemLabelFont(), getItemLabelColor(), getItemLabelBackgroundColor(), xw, yw + ydelta, zw, false, true); labelObj.setProperty(Object3D.ITEM_KEY, itemKey); world.add(labelObj); } else if (positioning.equals( ItemLabelPositioning.FRONT_AND_BACK)) { double zdelta = this.depth / 2 * offsets.getDZ(); Object3D labelObj1 = Object3D.createLabelObject(label, getItemLabelFont(), getItemLabelColor(), getItemLabelBackgroundColor(), xw, yw + ydelta, zw - zdelta, false, false); labelObj1.setProperty(Object3D.CLASS_KEY, "ItemLabel"); labelObj1.setProperty(Object3D.ITEM_KEY, itemKey); world.add(labelObj1); Object3D labelObj2 = Object3D.createLabelObject(label, getItemLabelFont(), getItemLabelColor(), getItemLabelBackgroundColor(), xw, yw + ydelta, zw + zdelta, true, false); labelObj2.setProperty(Object3D.CLASS_KEY, "ItemLabel"); labelObj2.setProperty(Object3D.ITEM_KEY, itemKey); world.add(labelObj2); } } } /** * Creates objects to represent the area segment between (x0, y0) and * (x1, y1). * * @param x0 * @param y0 * @param x1 * @param y1 * @param z * @param ymin * @param ymax * @param color * @param clipColor * @param openingFace * @param closingFace * * @return A list of objects making up the segment. */ private List createSegment(double x0, double y0, double x1, double y1, double z, double base, double ymin, double ymax, Color color, Color baseColor, Color clipColor, boolean openingFace, boolean closingFace) { List result = new ArrayList<>(2); // either there is a crossing or there is not if (!isBaselineCrossed(y0, y1, base)) { Object3D segment = createSegmentWithoutCrossing(x0, y0, x1, y1, z, base, ymin, ymax, color, baseColor, clipColor, openingFace, closingFace); result.add(segment); } else { result.addAll(createSegmentWithCrossing(x0, y0, x1, y1, z, base, ymin, ymax, color, baseColor, clipColor, openingFace, closingFace)); } return result; } /** * Returns {@code true} if the two values are on opposite sides of * the baseline. If the data values cross the baseline, then we need * to construct two 3D objects to represent the data, whereas if there is * no crossing, a single 3D object will be sufficient. * * @param y0 the first value. * @param y1 the second value. * @param baseline the baseline. * * @return A boolean. */ private boolean isBaselineCrossed(double y0, double y1, double baseline) { return (y0 > baseline && y1 < baseline) || (y0 < baseline && y1 > baseline); } private Object3D createSegmentWithoutCrossing(double x0, double y0, double x1, double y1, double z, double base, double ymin, double ymax, Color color, Color baseColor, Color clipColor, boolean openingFace, boolean closingFace) { boolean positive = y0 > base || y1 > base; if (positive) { Object3D pos = createPositiveArea(x0, y0, x1, y1, base, z, new Range(ymin, ymax), color, openingFace, closingFace); return pos; } else { Object3D neg = createNegativeArea(x0, y0, x1, y1, base, z, new Range(ymin, ymax), color, openingFace, closingFace); return neg; } } private List createSegmentWithCrossing(double x0, double y0, double x1, double y1, double z, double base, double ymin, double ymax, Color color, Color baseColor, Color clipColor, boolean openingFace, boolean closingFace) { List result = new ArrayList<>(2); Range range = new Range(ymin, ymax); // find the crossing point double ydelta = Math.abs(y1 - y0); double factor = 0; if (ydelta != 0.0) { factor = Math.abs(y0 - base) / ydelta; } double xcross = x0 + factor * (x1 - x0); if (y0 > base) { Object3D pos = createPositiveArea(x0, y0, xcross, base, base, z, range, color, openingFace, closingFace); if (pos != null) { result.add(pos); } Object3D neg = createNegativeArea(xcross, base, x1, y1, base, z, range, color, openingFace, closingFace); if (neg != null) { result.add(neg); } } else { Object3D neg = createNegativeArea(x0, y0, xcross, base, base, z, range, color, openingFace, closingFace); if (neg != null) { result.add(neg); } Object3D pos = createPositiveArea(xcross, base, x1, y1, base, z, range, color, openingFace, closingFace); if (pos != null) { result.add(pos); } } return result; } /** * A utility method that returns the fraction (x - x0) / (x1 - x0), which * is used for some interpolation calculations. * * @param x the x-value. * @param x0 the start of a range. * @param x1 the end of a range. * * @return The fractional value of x along the range x0 to x1. */ private double fraction(double x, double x0, double x1) { double dist = x - x0; double length = x1 - x0; return dist / length; } /** * A value in world units that is considered small enough to be not * significant. We use this to check if two coordinates are "more or less" * the same. */ private static final double EPSILON = 0.001; /** * Creates a 3D object to represent a positive "area", taking into account * that the visible range can be restricted. * * @param color the color ({@code null} not permitted). * @param wx0 * @param wy0 * @param wx1 * @param wy1 * @param wbase * @param wz * @param range * @param openingFace * @param closingFace * * @return A 3D object or {@code null}. */ private Object3D createPositiveArea(double wx0, double wy0, double wx1, double wy1, double wbase, double wz, Range range, Color color, boolean openingFace, boolean closingFace) { if (!range.intersects(wy0, wbase) && !range.intersects(wy1, wbase)) { return null; } double wy00 = range.peggedValue(wy0); double wy11 = range.peggedValue(wy1); double wbb = range.peggedValue(wbase); double wx00 = wx0; if (wy0 < range.getMin()) { wx00 = wx0 + (wx1 - wx0) * fraction(wy00, wy0, wy1); } double wx11 = wx1; if (wy1 < range.getMin()) { wx11 = wx1 - (wx1 - wx0) * fraction(wy11, wy1, wy0); } double wx22 = Double.NaN; // bogus boolean p2required = Utils2D.spans(range.getMax(), wy0, wy1); if (p2required) { wx22 = wx0 + (wx1 - wx0) * fraction(range.getMax(), wy0, wy1); } double delta = this.depth / 2.0; // create an area shape Object3D obj = new Object3D(color, true); obj.addVertex(wx00, wbb, wz - delta); obj.addVertex(wx00, wbb, wz + delta); boolean leftSide = false; if (Math.abs(wy00 - wbb) > EPSILON) { leftSide = true; obj.addVertex(wx00, wy00, wz - delta); obj.addVertex(wx00, wy00, wz + delta); } if (p2required) { obj.addVertex(wx22, range.getMax(), wz - delta); obj.addVertex(wx22, range.getMax(), wz + delta); } obj.addVertex(wx11, wy11, wz - delta); obj.addVertex(wx11, wy11, wz + delta); boolean rightSide = false; if (Math.abs(wy11 - wbb) > EPSILON) { rightSide = true; obj.addVertex(wx11, wbb, wz - delta); obj.addVertex(wx11, wbb, wz + delta); } int vertices = obj.getVertexCount(); if (vertices == 10) { obj.addFace(new int[] {0, 2, 4, 6, 8}); // front obj.addFace(new int[] {1, 9, 7, 5, 3}); // rear obj.addFace(new int[] {0, 8, 9, 1}); // base obj.addFace(new int[] {2, 3, 5, 4}); // top 1 obj.addFace(new int[] {4, 5, 7, 6}); // top 2 if (openingFace) { obj.addFace(new int[] {0, 1, 3, 2}); } if (closingFace) { obj.addFace(new int[] {6, 7, 9, 8}); } } else if (vertices == 8) { obj.addFace(new int[] {0, 2, 4, 6}); // front obj.addFace(new int[] {7, 5, 3, 1}); // rear if (!leftSide) { obj.addFace(new int[] {0, 1, 3, 2}); // top left } obj.addFace(new int[] {2, 3, 5, 4}); // top 1 if (!rightSide) { obj.addFace(new int[] {4, 5, 7, 6}); // top 2 } obj.addFace(new int[] {1, 0, 6, 7}); // base if (openingFace) { obj.addFace(new int[] {0, 1, 3, 2}); } if (closingFace) { obj.addFace(new int[] {4, 5, 7, 6}); } } else if (vertices == 6) { obj.addFace(new int[] {0, 2, 4}); // front obj.addFace(new int[] {5, 3, 1}); // rear if (leftSide) { obj.addFace(new int[] {3, 5, 4, 2}); // top if (openingFace) { obj.addFace(new int[] {0, 1, 3, 2}); } } else { obj.addFace(new int[] {0, 1, 3, 2}); // top if (closingFace) { obj.addFace(new int[] {2, 3, 5, 4}); } } obj.addFace(new int[] {0, 4, 5, 1}); // base } else { obj.addFace(new int[] {0, 1, 3, 2}); obj.addFace(new int[] {2, 3, 1, 0}); } return obj; } /** * Creates a negative area shape from (wx0, wy0) to (wx1, wy1) with the * base at wbase (it is assumed that both wy0 and wy1 are less than wbase). * * @param wx0 * @param wy0 * @param wx1 * @param wy1 * @param wbase * @param wz * @param range * @param color * @param openingFace * @param closingFace * * @return An object representing the area shape (or {@code null}). */ private Object3D createNegativeArea(double wx0, double wy0, double wx1, double wy1, double wbase, double wz, Range range, Color color, boolean openingFace, boolean closingFace) { if (!range.intersects(wy0, wbase) && !range.intersects(wy1, wbase)) { return null; } double wy00 = range.peggedValue(wy0); double wy11 = range.peggedValue(wy1); double wbb = range.peggedValue(wbase); double wx00 = wx0; if (wy0 > range.getMax()) { wx00 = wx0 + (wx1 - wx0) * fraction(wy00, wy0, wy1); } double wx11 = wx1; if (wy1 > range.getMax()) { wx11 = wx1 - (wx1 - wx0) * fraction(wy11, wy1, wy0); } double wx22 = (wx00 + wx11) / 2.0; // bogus boolean p2required = Utils2D.spans(range.getMin(), wy0, wy1); if (p2required) { wx22 = wx0 + (wx1 - wx0) * fraction(range.getMin(), wy0, wy1); } double delta = this.depth / 2.0; // create an area shape Object3D obj = new Object3D(color, true); obj.addVertex(wx00, wbb, wz - delta); obj.addVertex(wx00, wbb, wz + delta); boolean leftSide = false; if (Math.abs(wy00 - wbb) > EPSILON) { leftSide = true; obj.addVertex(wx00, wy00, wz - delta); obj.addVertex(wx00, wy00, wz + delta); } if (p2required) { obj.addVertex(wx22, range.getMin(), wz - delta); obj.addVertex(wx22, range.getMin(), wz + delta); } obj.addVertex(wx11, wy11, wz - delta); obj.addVertex(wx11, wy11, wz + delta); boolean rightSide = false; if (Math.abs(wy11 - wbb) > EPSILON) { obj.addVertex(wx11, wbb, wz - delta); obj.addVertex(wx11, wbb, wz + delta); } int vertices = obj.getVertexCount(); if (vertices == 10) { obj.addFace(new int[] {8, 6, 4, 2, 0}); // front obj.addFace(new int[] {1, 3, 5, 7, 9}); // rear obj.addFace(new int[] {1, 9, 8, 0}); // base obj.addFace(new int[] {4, 5, 3, 2}); // top 1 obj.addFace(new int[] {6, 7, 5, 4}); // top 2 if (openingFace) { obj.addFace(new int[] {2, 3, 1, 0}); } if (closingFace) { obj.addFace(new int[] {8, 9, 7, 6}); } } else if (vertices == 8) { obj.addFace(new int[] {2, 0, 6, 4}); // front obj.addFace(new int[] {1, 3, 5, 7}); // rear obj.addFace(new int[] {0, 1, 7, 6}); // base if (!leftSide) { obj.addFace(new int[] {2, 3, 1, 0}); } obj.addFace(new int[] {3, 2, 4, 5}); // negative top if (!rightSide) { obj.addFace(new int[] {6, 7, 5, 4}); } if (openingFace) { obj.addFace(new int[] {1, 0, 2, 3}); } if (closingFace) { obj.addFace(new int[] {5, 4, 6, 7}); } } else if (vertices == 6) { obj.addFace(new int[] {4, 2, 0}); // front obj.addFace(new int[] {1, 3, 5}); // rear if (leftSide) { obj.addFace(new int[] {4, 5, 3, 2}); // negative top if (openingFace) { obj.addFace(new int[] {1, 0, 2, 3}); } } else { obj.addFace(new int[] {2, 3, 1, 0}); // negative top if (closingFace) { obj.addFace(new int[] {3, 2, 4, 5}); } } obj.addFace(new int[] {0, 1, 5, 4}); // base } else { obj.addFace(new int[] {0, 1, 3, 2}); obj.addFace(new int[] {2, 3, 1, 0}); } return obj; } /** * Tests this renderer for equality with an arbitrary object. * * @param obj the object ({@code null} permitted). * * @return A boolean. */ @Override public boolean equals(Object obj) { if (obj == this) { return true; } if (!(obj instanceof AreaRenderer3D)) { return false; } AreaRenderer3D that = (AreaRenderer3D) obj; if (this.base != that.base) { return false; } if (!ObjectUtils.equals(this.baseColor, that.baseColor)) { return false; } if (this.depth != that.depth) { return false; } return super.equals(obj); } } orson-charts-2.1.0/src/main/java/org/jfree/chart3d/renderer/category/BarRenderer3D.java000066400000000000000000000422401417331271500306600ustar00rootroot00000000000000/* =========================================================== * Orson Charts : a 3D chart library for the Java(tm) platform * =========================================================== * * (C)opyright 2013-2022, by David Gilbert. All rights reserved. * * https://github.com/jfree/orson-charts * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . * * [Oracle and Java are registered trademarks of Oracle and/or its affiliates. * Other names may be trademarks of their respective owners.] * * If you do not wish to be bound by the terms of the GPL, an alternative * commercial license can be purchased. For details, please see visit the * Orson Charts home page: * * http://www.object-refinery.com/orsoncharts/index.html * */ package org.jfree.chart3d.renderer.category; import java.awt.Color; import java.io.Serializable; import org.jfree.chart3d.Chart3DFactory; import org.jfree.chart3d.axis.CategoryAxis3D; import org.jfree.chart3d.axis.ValueAxis3D; import org.jfree.chart3d.data.DataUtils; import org.jfree.chart3d.data.KeyedValues3DItemKey; import org.jfree.chart3d.data.Range; import org.jfree.chart3d.data.Values3D; import org.jfree.chart3d.data.category.CategoryDataset3D; import org.jfree.chart3d.graphics3d.Dimension3D; import org.jfree.chart3d.graphics3d.Object3D; import org.jfree.chart3d.graphics3d.World; import org.jfree.chart3d.internal.ObjectUtils; import org.jfree.chart3d.label.ItemLabelPositioning; import org.jfree.chart3d.plot.CategoryPlot3D; import org.jfree.chart3d.renderer.Renderer3DChangeEvent; /** * A renderer for creating 3D bar charts from a {@link CategoryDataset3D} (for * use with a {@link CategoryPlot3D}). For example: *
* BarChart3DDemo1.svg *
* (refer to {@code BarChart3DDemo1.java} for the code to generate the * above chart). *

* There is a factory method to create a chart using this renderer - see * {@link Chart3DFactory#createBarChart(String, String, CategoryDataset3D, * String, String, String)}. *

* NOTE: This class is serializable, but the serialization format is subject * to change in future releases and should not be relied upon for persisting * instances of this class. */ @SuppressWarnings("serial") public class BarRenderer3D extends AbstractCategoryRenderer3D implements Serializable { /** The base of the bars - defaults to 0.0. */ private double base; /** The bar width as a percentage of the column width. */ private double barXWidth; /** The bar width as a percentage of the row width. */ private double barZWidth; /** * The color source used to fetch the color for the base of bars where * the actual base of the bar is *outside* of the current axis range * (that is, the bar is "cropped"). If this is {@code null}, then * the regular bar color is used. */ private CategoryColorSource baseColorSource; /** * The paint source used to fetch the color for the top of bars where * the actual top of the bar is *outside* of the current axis range * (that is, the bar is "cropped"). If this is {@code null} then the * bar top is always drawn using the series paint. */ private CategoryColorSource topColorSource; /** * Creates a new renderer with default attribute values. */ public BarRenderer3D() { this.base = 0.0; this.barXWidth = 0.8; this.barZWidth = 0.5; this.baseColorSource = new StandardCategoryColorSource(Color.WHITE); this.topColorSource = new StandardCategoryColorSource(Color.BLACK); } /** * Returns the base value for the bars. The default value * is {@code 0.0}. * * @return The base value for the bars. * * @see #setBase(double) */ public double getBase() { return this.base; } /** * Sets the base value for the bars and fires a * {@link org.jfree.chart3d.renderer.Renderer3DChangeEvent}. * * @param base the new base value. * * @see #getBase() */ public void setBase(double base) { this.base = base; fireChangeEvent(true); } /** * Returns the bar width as a percentage of the column width. * The default value is {@code 0.8} (the total width of each column * in world units is {@code 1.0}, so the default leaves a small gap * between each bar). * * @return The bar width (in world units). */ public double getBarXWidth() { return this.barXWidth; } /** * Sets the the bar width as a percentage of the column width and * fires a {@link Renderer3DChangeEvent}. * * @param barXWidth the new width. */ public void setBarXWidth(double barXWidth) { this.barXWidth = barXWidth; fireChangeEvent(true); } /** * Returns the bar width as a percentage of the row width. * The default value is {@code 0.8}. * * @return The bar width. */ public double getBarZWidth() { return this.barZWidth; } /** * Sets the the bar width as a percentage of the row width and * fires a {@link org.jfree.chart3d.renderer.Renderer3DChangeEvent}. * * @param barZWidth the new width. */ public void setBarZWidth(double barZWidth) { this.barZWidth = barZWidth; fireChangeEvent(true); } /** * Returns the object used to fetch the color for the base of bars * where the base of the bar is "cropped" (on account of the base value * falling outside of the bounds of the y-axis). This is used to give a * visual indication to the end-user that the bar on display is cropped. * If this paint source is {@code null}, the regular series color * will be used for the top of the bars. * * @return A paint source (possibly {@code null}). */ public CategoryColorSource getBaseColorSource() { return this.baseColorSource; } /** * Sets the object that determines the color to use for the base of bars * where the base value falls outside the axis range, and sends a * {@link Renderer3DChangeEvent} to all registered listeners. If you set * this to {@code null}, the regular series color will be used to draw * the base of the bar, but it will be harder for the end-user to know that * only a section of the bar is visible in the chart. Note that the * default base paint source returns {@code Color.WHITE} always. * * @param source the source ({@code null} permitted). * * @see #getBaseColorSource() * @see #getTopColorSource() */ public void setBaseColorSource(CategoryColorSource source) { this.baseColorSource = source; fireChangeEvent(true); } /** * Returns the object used to fetch the color for the top of bars * where the top of the bar is "cropped" (on account of the data value * falling outside of the bounds of the y-axis). This is used to give a * visual indication to the end-user that the bar on display is cropped. * If this paint source is {@code null}, the regular series color * will be used for the top of the bars. * * @return A paint source (possibly {@code null}). */ public CategoryColorSource getTopColorSource() { return this.topColorSource; } /** * Sets the object used to fetch the color for the top of bars where the * top of the bar is "cropped", and sends a {@link Renderer3DChangeEvent} * to all registered listeners. * * @param source the source ({@code null} permitted). * * @see #getTopColorSource() * @see #getBaseColorSource() */ public void setTopColorSource(CategoryColorSource source) { this.topColorSource = source; fireChangeEvent(true); } /** * Returns the range of values that will be required on the value axis * to see all the data from the dataset. We override the method to * include in the range the base value for the bars. * * @param data the data ({@code null} not permitted). * * @return The range (possibly {@code null}) */ @Override public Range findValueRange(Values3D data) { return DataUtils.findValueRange(data, this.base); } /** * Constructs and places one item from the specified dataset into the given * world. This method will be called by the {@link CategoryPlot3D} class * while iterating over the items in the dataset. * * @param dataset the dataset ({@code null} not permitted). * @param series the series index. * @param row the row index. * @param column the column index. * @param world the world ({@code null} not permitted). * @param dimensions the plot dimensions ({@code null} not permitted). * @param xOffset the x-offset. * @param yOffset the y-offset. * @param zOffset the z-offset. */ @Override public void composeItem(CategoryDataset3D dataset, int series, int row, int column, World world, Dimension3D dimensions, double xOffset, double yOffset, double zOffset) { double value = dataset.getDoubleValue(series, row, column); if (Double.isNaN(value)) { return; } // delegate to a separate method that is reused by the // StackedBarRenderer3D subclass... composeItem(value, this.base, dataset, series, row, column, world, dimensions, xOffset, yOffset, zOffset); } /** * Performs the actual work of composing a bar to represent one item in the * dataset. This method is reused by the {@link StackedBarRenderer3D} * subclass. * * @param value the data value (top of the bar). * @param barBase the base value for the bar. * @param dataset the dataset. * @param series the series index. * @param row the row index. * @param column the column index. * @param world the world. * @param dimensions the plot dimensions. * @param xOffset the x-offset. * @param yOffset the y-offset. * @param zOffset the z-offset. */ @SuppressWarnings("unchecked") protected void composeItem(double value, double barBase, CategoryDataset3D dataset, int series, int row, int column, World world, Dimension3D dimensions, double xOffset, double yOffset, double zOffset) { Comparable seriesKey = dataset.getSeriesKey(series); Comparable rowKey = dataset.getRowKey(row); Comparable columnKey = dataset.getColumnKey(column); double vlow = Math.min(barBase, value); double vhigh = Math.max(barBase, value); CategoryPlot3D plot = getPlot(); CategoryAxis3D rowAxis = plot.getRowAxis(); CategoryAxis3D columnAxis = plot.getColumnAxis(); ValueAxis3D valueAxis = plot.getValueAxis(); Range range = valueAxis.getRange(); if (!range.intersects(vlow, vhigh)) { return; // the bar is not visible for the given axis range } double vbase = range.peggedValue(vlow); double vtop = range.peggedValue(vhigh); boolean inverted = barBase > value; double rowValue = rowAxis.getCategoryValue(rowKey); double columnValue = columnAxis.getCategoryValue(columnKey); double width = dimensions.getWidth(); double height = dimensions.getHeight(); double depth = dimensions.getDepth(); double xx = columnAxis.translateToWorld(columnValue, width) + xOffset; double yy = valueAxis.translateToWorld(vtop, height) + yOffset; double zz = rowAxis.translateToWorld(rowValue, depth) + zOffset; double xw = this.barXWidth * columnAxis.getCategoryWidth(); double zw = this.barZWidth * rowAxis.getCategoryWidth(); double xxw = columnAxis.translateToWorld(xw, width); double xzw = rowAxis.translateToWorld(zw, depth); double basew = valueAxis.translateToWorld(vbase, height) + yOffset; Color color = getColorSource().getColor(series, row, column); Color baseColor = null; if (this.baseColorSource != null && !range.contains(this.base)) { baseColor = this.baseColorSource.getColor(series, row, column); } if (baseColor == null) { baseColor = color; } Color topColor = null; if (this.topColorSource != null && !range.contains(value)) { topColor = this.topColorSource.getColor(series, row, column); } if (topColor == null) { topColor = color; } Object3D bar = Object3D.createBar(xxw, xzw, xx, yy, zz, basew, color, baseColor, topColor, inverted); KeyedValues3DItemKey itemKey = new KeyedValues3DItemKey(seriesKey, rowKey, columnKey); bar.setProperty(Object3D.ITEM_KEY, itemKey); world.add(bar); drawItemLabels(world, dataset, itemKey, xx, yy, zz, basew, inverted); } /** * Draws the item labels. * * @param world the world. * @param dataset the dataset. * @param itemKey the item key. * @param xw the x-coordinate. * @param yw the y-coordinate. * @param zw the z-coordinate. * @param basew the base coordinate. * @param inverted is the y-axis inverted? */ protected void drawItemLabels(World world, CategoryDataset3D dataset, KeyedValues3DItemKey itemKey, double xw, double yw, double zw, double basew, boolean inverted) { ItemLabelPositioning positioning = getItemLabelPositioning(); if (getItemLabelGenerator() == null) { return; } String label = getItemLabelGenerator().generateItemLabel(dataset, itemKey.getSeriesKey(), itemKey.getRowKey(), itemKey.getColumnKey()); if (label != null) { Dimension3D dimensions = getPlot().getDimensions(); double dx = getItemLabelOffsets().getDX(); double dy = getItemLabelOffsets().getDY() * dimensions.getHeight(); double dz = getItemLabelOffsets().getDZ() * getBarZWidth(); double yy = yw; if (inverted) { yy = basew; dy = -dy; } if (positioning.equals(ItemLabelPositioning.CENTRAL)) { Object3D labelObj = Object3D.createLabelObject(label, getItemLabelFont(), getItemLabelColor(), getItemLabelBackgroundColor(), xw + dx, yy + dy, zw, false, true); labelObj.setProperty(Object3D.ITEM_KEY, itemKey); world.add(labelObj); } else if (positioning.equals( ItemLabelPositioning.FRONT_AND_BACK)) { Object3D labelObj1 = Object3D.createLabelObject(label, getItemLabelFont(), getItemLabelColor(), getItemLabelBackgroundColor(), xw + dx, yy + dy, zw + dz, false, false); labelObj1.setProperty(Object3D.ITEM_KEY, itemKey); world.add(labelObj1); Object3D labelObj2 = Object3D.createLabelObject(label, getItemLabelFont(), getItemLabelColor(), getItemLabelBackgroundColor(), xw + dx, yy + dy, zw - dz, true, false); labelObj1.setProperty(Object3D.ITEM_KEY, itemKey); world.add(labelObj2); } } } /** * Tests this renderer for equality with an arbitrary object. * * @param obj the object ({@code null} permitted). * * @return A boolean. */ @Override public boolean equals(Object obj) { if (obj == this) { return true; } if (!(obj instanceof BarRenderer3D)) { return false; } BarRenderer3D that = (BarRenderer3D) obj; if (this.base != that.base) { return false; } if (this.barXWidth != that.barXWidth) { return false; } if (this.barZWidth != that.barZWidth) { return false; } if (!ObjectUtils.equals(this.baseColorSource, that.baseColorSource)) { return false; } if (!ObjectUtils.equals(this.topColorSource, that.topColorSource)) { return false; } return super.equals(obj); } } orson-charts-2.1.0/src/main/java/org/jfree/chart3d/renderer/category/CategoryColorSource.java000066400000000000000000000054351417331271500322400ustar00rootroot00000000000000/* =========================================================== * Orson Charts : a 3D chart library for the Java(tm) platform * =========================================================== * * (C)opyright 2013-2022, by David Gilbert. All rights reserved. * * https://github.com/jfree/orson-charts * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . * * [Oracle and Java are registered trademarks of Oracle and/or its affiliates. * Other names may be trademarks of their respective owners.] * * If you do not wish to be bound by the terms of the GPL, an alternative * commercial license can be purchased. For details, please see visit the * Orson Charts home page: * * http://www.object-refinery.com/orsoncharts/index.html * */ package org.jfree.chart3d.renderer.category; import java.awt.Color; /** * A color source that can supply the colors for category plots. This is the * interface through which the renderer will obtain colors for each data item * in the chart. A default implementation * ({@link StandardCategoryColorSource}) is provided and you can customise * the rendering colors by providing an alternate implementation. */ public interface CategoryColorSource { /** * Returns the color for one data item in the chart. We return a * {@code Color} rather than a paint, because some manipulations * are done for the shading during the 3D rendering. * * @param series the series index. * @param row the row index. * @param column the column index. * * @return The color. */ Color getColor(int series, int row, int column); /** * Returns the color to be used in the legend to represent the specified * series. * * @param series the series index. * * @return The color. */ Color getLegendColor(int series); /** * Restyles the source using the specified colors. Refer to the * implementing class to confirm the precise behaviour (typically all * existing color settings are cleared and the specified colors are * installed as the new defaults). * * @param colors the colors. * * @since 1.2 */ void style(Color... colors); } orson-charts-2.1.0/src/main/java/org/jfree/chart3d/renderer/category/CategoryRenderer3D.java000066400000000000000000000106331417331271500317320ustar00rootroot00000000000000/* =========================================================== * Orson Charts : a 3D chart library for the Java(tm) platform * =========================================================== * * (C)opyright 2013-2022, by David Gilbert. All rights reserved. * * https://github.com/jfree/orson-charts * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . * * [Oracle and Java are registered trademarks of Oracle and/or its affiliates. * Other names may be trademarks of their respective owners.] * * If you do not wish to be bound by the terms of the GPL, an alternative * commercial license can be purchased. For details, please see visit the * Orson Charts home page: * * http://www.object-refinery.com/orsoncharts/index.html * */ package org.jfree.chart3d.renderer.category; import java.awt.Color; import org.jfree.chart3d.data.Range; import org.jfree.chart3d.data.Values3D; import org.jfree.chart3d.data.category.CategoryDataset3D; import org.jfree.chart3d.graphics3d.Dimension3D; import org.jfree.chart3d.graphics3d.World; import org.jfree.chart3d.plot.CategoryPlot3D; import org.jfree.chart3d.renderer.Renderer3D; import org.jfree.chart3d.renderer.Renderer3DChangeEvent; /** * Defines the methods that all renderers must support to work with a * {@link CategoryPlot3D}. */ public interface CategoryRenderer3D extends Renderer3D { /** * Returns the plot that this renderer is assigned to. * * @return The plot (possibly {@code null}). */ CategoryPlot3D getPlot(); /** * Sets the plot that the renderer is assigned to. Although this method * is part of the public API, client code should not need to call it. * * @param plot the plot ({@code null} permitted). */ void setPlot(CategoryPlot3D plot); /** * Returns the color source for the renderer, which is an object that * is responsible for providing the colors used by the renderer to draw * data (and legend) items. * * @return The paint source (never {@code null}). */ CategoryColorSource getColorSource(); /** * Sets the color source for the renderer and sends a * {@link Renderer3DChangeEvent} to all registered listeners. * * @param source the color source ({@code null} not permitted). */ void setColorSource(CategoryColorSource source); /** * Sets the colors for the renderer. * * @param colors the colors. * * @since 1.2 */ void setColors(Color... colors); /** * Returns the range that should be used on the value axis to display all * the specified data using this renderer. Normally this will return the * minimum and maximum values in the dataset, but some renderers require * a larger range (for example, the stacked bar renderer). * * @param data the data values ({@code null} not permitted). * * @return The data range. */ Range findValueRange(Values3D data); /** * Constructs and places one item from the specified dataset into the given * world. This method will be called by the {@link CategoryPlot3D} class * while iterating over the items in the dataset. * * @param dataset the dataset ({@code null} not permitted). * @param series the series index. * @param row the row index. * @param column the column index. * @param world the world ({@code null} not permitted). * @param dimensions the plot dimensions ({@code null} not permitted). * @param xOffset the x-offset. * @param yOffset the y-offset. * @param zOffset the z-offset. */ void composeItem(CategoryDataset3D dataset, int series, int row, int column, World world, Dimension3D dimensions, double xOffset, double yOffset, double zOffset); } orson-charts-2.1.0/src/main/java/org/jfree/chart3d/renderer/category/LineRenderer3D.java000066400000000000000000001620411417331271500310450ustar00rootroot00000000000000/* =========================================================== * Orson Charts : a 3D chart library for the Java(tm) platform * =========================================================== * * (C)opyright 2013-2022, by David Gilbert. All rights reserved. * * https://github.com/jfree/orson-charts * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . * * [Oracle and Java are registered trademarks of Oracle and/or its affiliates. * Other names may be trademarks of their respective owners.] * * If you do not wish to be bound by the terms of the GPL, an alternative * commercial license can be purchased. For details, please see visit the * Orson Charts home page: * * http://www.object-refinery.com/orsoncharts/index.html * */ package org.jfree.chart3d.renderer.category; import java.awt.Color; import java.io.Serializable; import org.jfree.chart3d.Chart3D; import org.jfree.chart3d.Chart3DFactory; import org.jfree.chart3d.axis.CategoryAxis3D; import org.jfree.chart3d.axis.ValueAxis3D; import org.jfree.chart3d.data.KeyedValues3DItemKey; import org.jfree.chart3d.data.Range; import org.jfree.chart3d.data.category.CategoryDataset3D; import org.jfree.chart3d.graphics3d.Dimension3D; import org.jfree.chart3d.graphics3d.Object3D; import org.jfree.chart3d.graphics3d.Offset3D; import org.jfree.chart3d.graphics3d.World; import org.jfree.chart3d.internal.ObjectUtils; import org.jfree.chart3d.label.ItemLabelPositioning; import org.jfree.chart3d.plot.CategoryPlot3D; import org.jfree.chart3d.renderer.Renderer3DChangeEvent; /** * A renderer that can be used with the {@link CategoryPlot3D} class to create * 3D lines charts from data in a {@link CategoryDataset3D}. The * {@code createLineChart()} method in the {@link Chart3DFactory} class * will construct a chart that uses this renderer. Here is a sample: *
* LineChart3DDemo1.svg *
* (refer to {@code LineChart3DDemo1.java} for the code to generate the * above chart). *

* Some attributes in the renderer are specified in "world units" - see the * {@link Chart3D} class description for more information about world units. *

* There is a factory method to create a chart using this renderer - see * {@link Chart3DFactory#createLineChart(String, String, CategoryDataset3D, * String, String, String)}. *

* NOTE: This class is serializable, but the serialization format is subject * to change in future releases and should not be relied upon for persisting * instances of this class. */ @SuppressWarnings("serial") public class LineRenderer3D extends AbstractCategoryRenderer3D implements Serializable { /** The line width (in world units). */ private double lineWidth; /** The line height (in world units). */ private double lineHeight; /** * For isolated data values this attribute controls the width (x-axis) of * the box representing the data item, it is expressed as a percentage of * the category width. */ private double isolatedItemWidthPercent; /** * The color source that determines the color used to highlight clipped * items in the chart. */ private CategoryColorSource clipColorSource; /** * Creates a new instance with default attribute values. */ public LineRenderer3D() { this.lineWidth = 0.4; this.lineHeight = 0.2; this.isolatedItemWidthPercent = 0.25; this.clipColorSource = new StandardCategoryColorSource(Color.RED); } /** * Returns the line width in world units. The default value is * {@code 0.4}. * * @return The line width in world units. */ public double getLineWidth() { return this.lineWidth; } /** * Sets the line width (in world units) and sends a * {@link Renderer3DChangeEvent} to all registered listeners. * * @param width the width (in world units). */ public void setLineWidth(double width) { this.lineWidth = width; fireChangeEvent(true); } /** * Returns the line height in world units. The default value is * {@code 0.2}. * * @return The line height in world units. */ public double getLineHeight() { return this.lineHeight; } /** * Sets the line height (in world units) and sends a * {@link Renderer3DChangeEvent} to all registered listeners. * * @param height the height (in world units). */ public void setLineHeight(double height) { this.lineHeight = height; fireChangeEvent(true); } /** * Returns the width for isolated data items as a percentage of the * category width. The default value is 0.25 (twenty five percent). * * @return The width percentage. * * @since 1.3 */ public double getIsolatedItemWidthPercent() { return this.isolatedItemWidthPercent; } /** * Sets the width for isolated data items as a percentage of the category * width and sends a change event to all registered listeners. * * @param percent the new percentage. * * @since 1.3 */ public void setIsolatedItemWidthPercent(double percent) { this.isolatedItemWidthPercent = percent; fireChangeEvent(true); } /** * Returns the color source used to determine the color used to highlight * clipping in the chart elements. If the source is {@code null}, * then the regular series color is used instead. * * @return The color source (possibly {@code null}). */ public CategoryColorSource getClipColorSource() { return this.clipColorSource; } /** * Sets the color source that determines the color used to highlight * clipping in the chart elements, and sends a {@link Renderer3DChangeEvent} * to all registered listeners. * * @param source the source ({@code null} permitted). */ public void setClipColorSource(CategoryColorSource source) { this.clipColorSource = source; fireChangeEvent(true); } /** * Constructs and places one item from the specified dataset into the given * world. This method will be called by the {@link CategoryPlot3D} class * while iterating over the items in the dataset. * * @param dataset the dataset ({@code null} not permitted). * @param series the series index. * @param row the row index. * @param column the column index. * @param world the world ({@code null} not permitted). * @param dimensions the plot dimensions ({@code null} not permitted). * @param xOffset the x-offset. * @param yOffset the y-offset. * @param zOffset the z-offset. */ @Override @SuppressWarnings("unchecked") public void composeItem(CategoryDataset3D dataset, int series, int row, int column, World world, Dimension3D dimensions, double xOffset, double yOffset, double zOffset) { // there is a lot of brute force code underneath this compose method // because I haven't seen the pattern yet that will let me reduce it // to something more elegant...probably I'm not smart enough. Number y = (Number) dataset.getValue(series, row, column); Number yprev = null; if (column > 0) { yprev = (Number) dataset.getValue(series, row, column - 1); } Number ynext = null; if (column < dataset.getColumnCount() - 1) { ynext = (Number) dataset.getValue(series, row, column + 1); } CategoryPlot3D plot = getPlot(); CategoryAxis3D rowAxis = plot.getRowAxis(); CategoryAxis3D columnAxis = plot.getColumnAxis(); ValueAxis3D valueAxis = plot.getValueAxis(); Range r = valueAxis.getRange(); Comparable seriesKey = dataset.getSeriesKey(series); Comparable rowKey = dataset.getRowKey(row); Comparable columnKey = dataset.getColumnKey(column); double rowValue = rowAxis.getCategoryValue(rowKey); double columnValue = columnAxis.getCategoryValue(columnKey); double ww = dimensions.getWidth(); double hh = dimensions.getHeight(); double dd = dimensions.getDepth(); // for any data value, we'll try to create two line segments, one to // the left of the value and one to the right of the value (each // halfway to the adjacent data value). If the adjacent data values // are null (or don't exist, as in the case of the first and last data // items, then we can create an isolated segment to represent the data // item. The final consideration is whether the opening and closing // faces of each segment are filled or not (if the segment connects to // another segment, there is no need to fill the end face) boolean createLeftSegment, createRightSegment, createIsolatedSegment; boolean leftOpen = false; boolean leftClose = false; boolean rightOpen = false; boolean rightClose = false; if (column == 0) { // first column is a special case createLeftSegment = false; // never for first item if (dataset.getColumnCount() == 1) { createRightSegment = false; createIsolatedSegment = (y != null); } else { createRightSegment = (y != null && ynext != null); rightOpen = true; rightClose = false; createIsolatedSegment = (y != null && ynext == null); } } else if (column == dataset.getColumnCount() - 1) { // last column createRightSegment = false; // never for the last item createLeftSegment = (y != null && yprev != null); leftOpen = false; leftClose = true; createIsolatedSegment = (y != null && yprev == null); } else { // this is the general case createLeftSegment = (y != null && yprev != null); leftOpen = false; leftClose = (createLeftSegment && ynext == null); createRightSegment = (y != null && ynext != null); rightOpen = (createRightSegment && yprev == null); rightClose = false; createIsolatedSegment = (y != null && yprev == null && ynext == null); } // now that we know what we have to create, we'll need some info // for the construction double xw = columnAxis.translateToWorld(columnValue, ww) + xOffset; double yw = Double.NaN; if (y != null) { yw = valueAxis.translateToWorld(y.doubleValue(), hh) + yOffset; } double zw = rowAxis.translateToWorld(rowValue, dd) + zOffset; double ywmin = valueAxis.translateToWorld(r.getMin(), hh) + yOffset; double ywmax = valueAxis.translateToWorld(r.getMax(), hh) + yOffset; Color color = getColorSource().getColor(series, row, column); Color clipColor = color; if (getClipColorSource() != null) { Color c = getClipColorSource().getColor(series, row, column); if (c != null) { clipColor = c; } } KeyedValues3DItemKey itemKey = new KeyedValues3DItemKey(seriesKey, rowKey, columnKey); if (createLeftSegment) { Comparable prevColumnKey = dataset.getColumnKey(column - 1); double prevColumnValue = columnAxis.getCategoryValue(prevColumnKey); double prevColumnX = columnAxis.translateToWorld(prevColumnValue, ww) + xOffset; double xl = (prevColumnX + xw) / 2.0; double yprevw = valueAxis.translateToWorld(yprev.doubleValue(), hh) + yOffset; double yl = (yprevw + yw) / 2.0; Object3D left = createSegment(xl, yl, xw, yw, zw, this.lineWidth, this.lineHeight, ywmin, ywmax, color, clipColor, leftOpen, leftClose); if (left != null) { left.setProperty(Object3D.ITEM_KEY, itemKey); world.add(left); } } if (createRightSegment) { Comparable nextColumnKey = dataset.getColumnKey(column + 1); double nextColumnValue = columnAxis.getCategoryValue(nextColumnKey); double nextColumnX = columnAxis.translateToWorld(nextColumnValue, ww) + xOffset; double xr = (nextColumnX + xw) / 2.0; double ynextw = valueAxis.translateToWorld(ynext.doubleValue(), hh) + yOffset; double yr = (ynextw + yw) / 2.0; Object3D right = createSegment(xw, yw, xr, yr, zw, this.lineWidth, this.lineHeight, ywmin, ywmax, color, clipColor, rightOpen, rightClose); if (right != null) { right.setProperty(Object3D.ITEM_KEY, itemKey); world.add(right); } } if (createIsolatedSegment) { double cw = columnAxis.getCategoryWidth() * this.isolatedItemWidthPercent; double cww = columnAxis.translateToWorld(cw, ww); Object3D isolated = Object3D.createBox(xw, cww, yw, this.lineHeight, zw, this.lineWidth, color); if (isolated != null) { isolated.setProperty(Object3D.ITEM_KEY, itemKey); world.add(isolated); } } if (getItemLabelGenerator() != null && !Double.isNaN(yw) && yw >= ywmin && yw <= ywmax) { String label = getItemLabelGenerator().generateItemLabel(dataset, seriesKey, rowKey, columnKey); if (label != null) { ItemLabelPositioning positioning = getItemLabelPositioning(); Offset3D offsets = getItemLabelOffsets(); double dy = offsets.getDY() * dimensions.getHeight(); if (positioning.equals(ItemLabelPositioning.CENTRAL)) { Object3D labelObj = Object3D.createLabelObject(label, getItemLabelFont(), getItemLabelColor(), getItemLabelBackgroundColor(), xw, yw + dy, zw, false, true); labelObj.setProperty(Object3D.ITEM_KEY, itemKey); world.add(labelObj); } else if (positioning.equals( ItemLabelPositioning.FRONT_AND_BACK)) { double dz = this.lineWidth ; Object3D labelObj1 = Object3D.createLabelObject(label, getItemLabelFont(), getItemLabelColor(), getItemLabelBackgroundColor(), xw, yw, zw - dz, false, false); labelObj1.setProperty(Object3D.ITEM_KEY, itemKey); world.add(labelObj1); Object3D labelObj2 = Object3D.createLabelObject(label, getItemLabelFont(), getItemLabelColor(), getItemLabelBackgroundColor(), xw, yw, zw + dz, true, false); labelObj2.setProperty(Object3D.ITEM_KEY, itemKey); world.add(labelObj2); } } } } /** * Creates a segment of a line between (x0, y0, z) and (x1, y1, z), with * the specified line width and height, taking into account the minimum * and maximum world coordinates (in the y-direction, because it is assumed * that we have the full x and z-range required). * * @param x0 the starting x-coordinate. * @param y0 the starting x-coordinate. * @param x1 the ending x-coordinate. * @param y1 the ending y-coordinate. * @param z the z-coordinate. * @param lineWidth the line width (z-axis). * @param lineHeight the line height (y-axis). * @param ymin the lower bound for y-values. * @param ymax the upper bound for y-values. * @param color the segment color. * @param clipColor the clip color (for the faces in the segment that are * clipped against the edge of the world). * @param openingFace is an opening face required? * @param closingFace is a closing face required? * * @return A 3D object that is a segment in a line. */ private Object3D createSegment(double x0, double y0, double x1, double y1, double z, double lineWidth, double lineHeight, double ymin, double ymax, Color color, Color clipColor, boolean openingFace, boolean closingFace) { double wdelta = lineWidth / 2.0; double hdelta = lineHeight / 2.0; double y0b = y0 - hdelta; double y0t = y0 + hdelta; double y1b = y1 - hdelta; double y1t = y1 + hdelta; double zf = z - wdelta; double zb = z + wdelta; double[] xpts = calcCrossPoints(x0, x1, y0b, y0t, y1b, y1t, ymin, ymax); Object3D seg = null; if (y0b >= ymax) { // CASE A seg = createSegmentA(x0, x1, xpts, y0b, y0t, y1b, y1t, ymin, ymax, zf, zb, color, clipColor, false, closingFace); } else if (y0t > ymax && y0b > ymin) { // CASE B seg = createSegmentB(x0, x1, xpts, y0b, y0t, y1b, y1t, ymin, ymax, zf, zb, color, clipColor, openingFace, closingFace); } else if (y0t > ymax && y0b <= ymin) { // CASE C seg = createSegmentC(x0, x1, xpts, y0b, y0t, y1b, y1t, ymin, ymax, zf, zb, color, clipColor, openingFace, closingFace); } else if (y0t > ymin && y0b >= ymin) { // CASE D seg = createSegmentD(x0, x1, xpts, y0b, y0t, y1b, y1t, ymin, ymax, zf, zb, color, clipColor, openingFace, closingFace); } else if (y0t > ymin && y0b < ymin) { // CASE E seg = createSegmentE(x0, x1, xpts, y0b, y0t, y1b, y1t, ymin, ymax, zf, zb, color, clipColor, openingFace, closingFace); } else if (y0t <= ymin) { // CASE F seg = createSegmentF(x0, x1, xpts, y0b, y0t, y1b, y1t, ymin, ymax, zf, zb, color, clipColor, false, closingFace); } return seg; } /** * Calculates the four intersection points between two horizontal lines * (ymin and ymax) and the lines (x0, y0b, x1, y1b) and (x0, y1t, x1, y1t) * and returns the x-coordinates in an array. * * @param x0 * @param x1 * @param y0b * @param y0t * @param y1b * @param y1t * @param ymin * @param ymax * * @return An array of 4 x-coordinates. */ private double[] calcCrossPoints(double x0, double x1, double y0b, double y0t, double y1b, double y1t, double ymin, double ymax) { double[] xpts = new double[] { Double.NaN, Double.NaN, Double.NaN, Double.NaN }; double factor = (y0b - ymin) / (y0b - y1b); xpts[0] = x0 + factor * (x1 - x0); factor = (y0t - ymin) / (y0t - y1t); xpts[1] = x0 + factor * (x1 - x0); factor = (y0b - ymax) / (y0b - y1b); xpts[2] = x0 + factor * (x1 - x0); factor = (y0t - ymax) / (y0t - y1t); xpts[3] = x0 + factor * (x1 - x0); return xpts; } /** * Creates a segment for the case where the start of the segment is * completely above the upper bound of the axis at the left side of the * chart. * * @param x0 * @param x1 * @param xpts * @param y0b * @param y0t * @param y1b * @param y1t * @param wmin * @param wmax * @param zf * @param zb * @param color * @param clipColor * @param openingFace ignored because there is no opening face for this * case. * @param closingFace * * @return A segment ({@code null} if the segment is entirely clipped). */ private Object3D createSegmentA(double x0, double x1, double[] xpts, double y0b, double y0t, double y1b, double y1t, double wmin, double wmax, double zf, double zb, Color color, Color clipColor, boolean openingFace, boolean closingFace) { if (y1b > wmax) { return null; // nothing is visible } if (y1t > wmax) { if (y1b >= wmin) { // create a triangle with the top and right Object3D seg = new Object3D(color, true); seg.setProperty(Object3D.COLOR_PREFIX + "clip", clipColor); seg.addVertex(xpts[2], wmax, zf); seg.addVertex(xpts[2], wmax, zb); seg.addVertex(x1, wmax, zf); seg.addVertex(x1, wmax, zb); seg.addVertex(x1, y1b, zf); seg.addVertex(x1, y1b, zb); seg.addFace(new int[] {0, 2, 4}); // front seg.addFace(new int[] {1, 5, 3}); // rear seg.addFace(new int[] {0, 1, 3, 2}, "clip"); // clip top seg.addFace(new int[] {4, 5, 1, 0}); // bottom if (closingFace) { seg.addFace(new int[] {2, 3, 5, 4}); } return seg; } else { Object3D seg = new Object3D(color, true); seg.setProperty(Object3D.COLOR_PREFIX + "clip", clipColor); seg.addVertex(xpts[2], wmax, zf); seg.addVertex(xpts[2], wmax, zb); seg.addVertex(x1, wmax, zf); seg.addVertex(x1, wmax, zb); seg.addVertex(x1, wmin, zf); seg.addVertex(x1, wmin, zb); seg.addVertex(xpts[0], wmin, zf); seg.addVertex(xpts[0], wmin, zb); seg.addFace(new int[] {0, 2, 4, 6}); // front seg.addFace(new int[] {1, 7, 5, 3}); // rear seg.addFace(new int[] {0, 1, 3, 2}); // clip top seg.addFace(new int[] {4, 5, 7, 6}, "clip"); // clip bottom seg.addFace(new int[] {6, 7, 1, 0}); // bottom if (closingFace) { seg.addFace(new int[] {2, 3, 5, 4}); } return seg; } } else if (y1t >= wmin) { if (y1b >= wmin) { Object3D seg = new Object3D(color, true); seg.setProperty(Object3D.COLOR_PREFIX + "clip", clipColor); seg.addVertex(xpts[2], wmax, zf); seg.addVertex(xpts[2], wmax, zb); seg.addVertex(xpts[3], wmax, zf); seg.addVertex(xpts[3], wmax, zb); seg.addVertex(x1, y1t, zf); seg.addVertex(x1, y1t, zb); seg.addVertex(x1, y1b, zf); seg.addVertex(x1, y1b, zb); seg.addFace(new int[] {0, 2, 4, 6}); // front seg.addFace(new int[] {1, 7, 5, 3}); // rear seg.addFace(new int[] {0, 1, 3, 2}, "clip"); // clip top seg.addFace(new int[] {2, 3, 5, 4}); // top seg.addFace(new int[] {6, 7, 1, 0}); // bottom if (closingFace) { seg.addFace(new int[] {4, 5, 7, 6}); } return seg; } else { Object3D seg = new Object3D(color, true); seg.setProperty(Object3D.COLOR_PREFIX + "clip", clipColor); seg.addVertex(xpts[2], wmax, zf); seg.addVertex(xpts[2], wmax, zb); seg.addVertex(xpts[3], wmax, zf); seg.addVertex(xpts[3], wmax, zb); seg.addVertex(x1, y1t, zf); seg.addVertex(x1, y1t, zb); seg.addVertex(x1, wmin, zf); seg.addVertex(x1, wmin, zb); seg.addVertex(xpts[0], wmin, zf); seg.addVertex(xpts[0], wmin, zb); seg.addFace(new int[] {0, 2, 4, 6, 8}); // front seg.addFace(new int[] {1, 9, 7, 5, 3}); // rear seg.addFace(new int[] {2, 3, 5, 4}); seg.addFace(new int[] {0, 1, 3, 2}, "clip"); // clip top seg.addFace(new int[] {6, 7, 9, 8}, "clip"); // clip bottom seg.addFace(new int[] {8, 9, 1, 0}); // there is no opening face in this case if (closingFace) { seg.addFace(new int[] {4, 5, 7, 6}); } return seg; } } else { Object3D seg = new Object3D(color, true); seg.setProperty(Object3D.COLOR_PREFIX + "clip", clipColor); seg.addVertex(xpts[2], wmax, zf); seg.addVertex(xpts[2], wmax, zb); seg.addVertex(xpts[3], wmax, zf); seg.addVertex(xpts[3], wmax, zb); seg.addVertex(xpts[1], wmin, zf); seg.addVertex(xpts[1], wmin, zb); seg.addVertex(xpts[0], wmin, zf); seg.addVertex(xpts[0], wmin, zb); seg.addFace(new int[] {0, 2, 4, 6}); // front seg.addFace(new int[] {1, 7, 5, 3}); // rear seg.addFace(new int[] {4, 2, 3, 5}); // top seg.addFace(new int[] {0, 6, 7, 1}); // bottom seg.addFace(new int[] {0, 1, 3, 2}, "clip"); // clip top seg.addFace(new int[] {4, 5, 7, 6}, "clip"); // clip bottom // there are no opening or closing faces in this case return seg; } } /** * Creates a segment for the case where the left end of the line spans * the axis maximum on the left side of the chart. * * @param x0 * @param x1 * @param xpts * @param y0b * @param y0t * @param y1b * @param y1t * @param wmin * @param wmax * @param zf * @param zb * @param color * @param clipColor * @param openingFace * @param closingFace * * @return A segment. */ private Object3D createSegmentB(double x0, double x1, double[] xpts, double y0b, double y0t, double y1b, double y1t, double wmin, double wmax, double zf, double zb, Color color, Color clipColor, boolean openingFace, boolean closingFace) { if (y1b >= wmax) { Object3D seg = new Object3D(color, true); seg.setProperty(Object3D.COLOR_PREFIX + "clip", clipColor); seg.addVertex(x0, y0b, zf); seg.addVertex(x0, y0b, zb); seg.addVertex(x0, wmax, zf); seg.addVertex(x0, wmax, zb); seg.addVertex(xpts[2], wmax, zf); seg.addVertex(xpts[2], wmax, zb); seg.addFace(new int[] {0, 2, 4}); // front seg.addFace(new int[] {1, 5, 3}); // rear seg.addFace(new int[] {0, 4, 5, 1}); // bottom seg.addFace(new int[] {2, 3, 5, 4}, "clip"); // clip top if (openingFace) { seg.addFace(new int[] {0, 1, 3, 2}); } // there is no closing face in this case return seg; } if (y1t > wmax) { if (y1b >= wmin) { Object3D seg = new Object3D(color, true); seg.setProperty(Object3D.COLOR_PREFIX + "clip", clipColor); seg.addVertex(x0, y0b, zf); seg.addVertex(x0, y0b, zb); seg.addVertex(x0, wmax, zf); seg.addVertex(x0, wmax, zb); seg.addVertex(x1, wmax, zf); seg.addVertex(x1, wmax, zb); seg.addVertex(x1, y1b, zf); seg.addVertex(x1, y1b, zb); seg.addFace(new int[] {0, 2, 4, 6}); // front seg.addFace(new int[] {1, 7, 5, 3}); // rear seg.addFace(new int[] {2, 3, 5, 4}, "clip"); // clip top seg.addFace(new int[] {0, 6, 7, 1}); // bottom if (openingFace) { seg.addFace(new int[] {0, 1, 3, 2}); } if (closingFace) { seg.addFace(new int[] {4, 5, 7, 6}); } return seg; } else { Object3D seg = new Object3D(color, true); seg.setProperty(Object3D.COLOR_PREFIX + "clip", clipColor); seg.addVertex(x0, y0b, zf); seg.addVertex(x0, y0b, zb); seg.addVertex(x0, wmax, zf); seg.addVertex(x0, wmax, zb); seg.addVertex(x1, wmax, zf); seg.addVertex(x1, wmax, zb); seg.addVertex(x1, wmin, zf); seg.addVertex(x1, wmin, zb); seg.addVertex(xpts[0], wmin, zf); seg.addVertex(xpts[0], wmin, zb); seg.addFace(new int[] {0, 2, 4, 6, 8}); // front seg.addFace(new int[] {1, 9, 7, 5, 3}); // rear seg.addFace(new int[] {2, 3, 5, 4}, "clip"); // clip top seg.addFace(new int[] {8, 6, 7, 9}, "clip"); // clip bottom seg.addFace(new int[] {0, 8, 9, 1}); if (openingFace) { seg.addFace(new int[] {0, 1, 3, 2}); } if (closingFace) { seg.addFace(new int[] {4, 5, 7, 6}); } return seg; } } if (y1t > wmin) { if (y1b >= wmin) { Object3D seg = new Object3D(color, true); seg.setProperty(Object3D.COLOR_PREFIX + "clip", clipColor); seg.addVertex(x0, y0b, zf); seg.addVertex(x0, y0b, zb); seg.addVertex(x0, wmax, zf); seg.addVertex(x0, wmax, zb); seg.addVertex(xpts[3], wmax, zf); seg.addVertex(xpts[3], wmax, zb); seg.addVertex(x1, y1t, zf); seg.addVertex(x1, y1t, zb); seg.addVertex(x1, y1b, zf); seg.addVertex(x1, y1b, zb); seg.addFace(new int[] {0, 2, 4, 6, 8}); // front seg.addFace(new int[] {1, 9, 7, 5, 3}); // rear seg.addFace(new int[] {2, 3, 5, 4}, "clip"); // clip top seg.addFace(new int[] {4, 5, 7, 6}); // top seg.addFace(new int[] {0, 8, 9, 1}); // bottom if (openingFace) { seg.addFace(new int[] {0, 1, 3, 2}); } if (closingFace) { seg.addFace(new int[] {6, 7, 9, 8}); } return seg; } else { Object3D seg = new Object3D(color, true); seg.setProperty(Object3D.COLOR_PREFIX + "clip", clipColor); seg.addVertex(x0, y0b, zf); seg.addVertex(x0, y0b, zb); seg.addVertex(x0, wmax, zf); seg.addVertex(x0, wmax, zb); seg.addVertex(xpts[3], wmax, zf); seg.addVertex(xpts[3], wmax, zb); seg.addVertex(x1, y1t, zf); seg.addVertex(x1, y1t, zb); seg.addVertex(x1, wmin, zf); seg.addVertex(x1, wmin, zb); seg.addVertex(xpts[0], wmin, zf); seg.addVertex(xpts[0], wmin, zb); seg.addFace(new int[] {0, 2, 4, 6, 8, 10}); // front seg.addFace(new int[] {1, 11, 9, 7, 5, 3}); // rear seg.addFace(new int[] {2, 3, 5, 4}, "clip"); // clip top seg.addFace(new int[] {4, 5, 7, 6}); // top seg.addFace(new int[] {8, 9, 11, 10}, "clip"); // clip bottom seg.addFace(new int[] {10, 11, 1, 0}); // bottom if (openingFace) { seg.addFace(new int[] {0, 1, 3, 2}); } if (closingFace) { seg.addFace(new int[] {6, 7, 9, 8}); } return seg; } } Object3D seg = new Object3D(color, true); seg.setProperty(Object3D.COLOR_PREFIX + "clip", clipColor); seg.addVertex(x0, y0b, zf); seg.addVertex(x0, y0b, zb); seg.addVertex(x0, wmax, zf); seg.addVertex(x0, wmax, zb); seg.addVertex(xpts[3], wmax, zf); seg.addVertex(xpts[3], wmax, zb); seg.addVertex(xpts[1], wmin, zf); seg.addVertex(xpts[1], wmin, zb); seg.addVertex(xpts[0], wmin, zf); seg.addVertex(xpts[0], wmin, zb); seg.addFace(new int[] {0, 2, 4, 6, 8}); // front seg.addFace(new int[] {1, 9, 7, 5, 3}); // rear seg.addFace(new int[] {2, 3, 5, 4}, "clip"); // clip top seg.addFace(new int[] {4, 5, 7, 6}); // top seg.addFace(new int[] {6, 7, 9, 8}, "clip"); // clip bottom seg.addFace(new int[] {8, 9, 1, 0}); // bottom if (openingFace) { seg.addFace(new int[] {0, 1, 3, 2}); } // there is no closing face in this case return seg; } /** * Creates a segment for the case where the line end spans the entire axis * range at the left side of the chart. * * @param x0 * @param x1 * @param xpts * @param y0b * @param y0t * @param y1b * @param y1t * @param wmin * @param wmax * @param zf * @param zb * @param color * @param clipColor * @param openingFace * @param closingFace * * @return A segment. */ private Object3D createSegmentC(double x0, double x1, double[] xpts, double y0b, double y0t, double y1b, double y1t, double wmin, double wmax, double zf, double zb, Color color, Color clipColor, boolean openingFace, boolean closingFace) { // the first 4 vertices and the opening face are common to all // segments in this case Object3D seg = new Object3D(color, true); seg.setProperty(Object3D.COLOR_PREFIX + "clip", clipColor); seg.addVertex(x0, wmin, zf); seg.addVertex(x0, wmin, zb); seg.addVertex(x0, wmax, zf); seg.addVertex(x0, wmax, zb); if (openingFace) { seg.addFace(new int[] {0, 1, 3, 2}); } if (y1b >= wmax) { seg.addVertex(xpts[2], wmax, zf); seg.addVertex(xpts[2], wmax, zb); seg.addVertex(xpts[0], wmin, zf); seg.addVertex(xpts[0], wmin, zb); seg.addFace(new int[] {0, 2, 4, 6}); // front seg.addFace(new int[] {1, 7, 5, 3}); // rear seg.addFace(new int[] {2, 3, 5, 4}, "clip"); // clip top seg.addFace(new int[] {4, 5, 7, 6}); // bottom seg.addFace(new int[] {7, 1, 0, 6}, "clip"); // bottom clip return seg; } if (y1t > wmax) { if (y1b >= wmin) { seg.addVertex(x1, wmax, zf); seg.addVertex(x1, wmax, zb); seg.addVertex(x1, y1b, zf); seg.addVertex(x1, y1b, zb); seg.addVertex(xpts[0], wmin, zf); seg.addVertex(xpts[0], wmin, zb); seg.addFace(new int[] {0, 2, 4, 6, 8}); // front seg.addFace(new int[] {1, 9, 7, 5, 3}); // rear seg.addFace(new int[] {2, 3, 5, 4}, "clip"); // top clip seg.addFace(new int[] {6, 7, 9, 8}); // bottom seg.addFace(new int[] {8, 9, 1, 0}, "clip"); // clip bottom if (closingFace) { seg.addFace(new int[] {4, 5, 7, 6}); } return seg; } else { seg.addVertex(x1, wmax, zf); seg.addVertex(x1, wmax, zb); seg.addVertex(x1, wmin, zf); seg.addVertex(x1, wmin, zb); seg.addFace(new int[] {0, 2, 4, 6}); // front seg.addFace(new int[] {1, 7, 5, 3}); // rear seg.addFace(new int[] {2, 3, 5, 4}, "clip"); // clip top seg.addFace(new int[] {4, 5, 7, 6}); // bottom seg.addFace(new int[] {7, 1, 0, 6}, "clip"); // bottom clip return seg; } } if (y1t > wmin) { if (y1b >= wmin) { return null; // in practice I don't think this case // can occur } else { seg.addVertex(xpts[3], wmax, zf); seg.addVertex(xpts[3], wmax, zb); seg.addVertex(x1, y1t, zf); seg.addVertex(x1, y1t, zb); seg.addVertex(x1, wmin, zf); seg.addVertex(x1, wmin, zb); seg.addFace(new int[] {0, 2, 4, 6, 8}); // front seg.addFace(new int[] {1, 9, 7, 5, 3}); // rear seg.addFace(new int[] {2, 3, 5, 4}, "clip"); // clip top seg.addFace(new int[] {4, 5, 7, 6}); // top seg.addFace(new int[] {9, 1, 0, 8}, "clip"); // clip bottom if (closingFace) { seg.addFace(new int[] {6, 7, 9, 8}); } return seg; } } seg.addVertex(xpts[3], wmax, zf); seg.addVertex(xpts[3], wmax, zb); seg.addVertex(xpts[1], wmin, zf); seg.addVertex(xpts[1], wmin, zb); seg.addFace(new int[] {0, 2, 4, 6}); // front seg.addFace(new int[] {1, 7, 5, 3}); // rear seg.addFace(new int[] {2, 3, 5, 4}, "clip"); // clip top seg.addFace(new int[] {4, 5, 7, 6}); // top seg.addFace(new int[] {6, 7, 1, 0}, "clip"); // clip bottom return seg; } /** * Creates a segment for the case where the segment is contained within * the axis range at the left side. * * @param x0 * @param x1 * @param xpts * @param y0b * @param y0t * @param y1b * @param y1t * @param wmin * @param wmax * @param zf * @param zb * @param color * @param clipColor * @param openingFace * @param closingFace * * @return A segment. */ private Object3D createSegmentD(double x0, double x1, double[] xpts, double y0b, double y0t, double y1b, double y1t, double wmin, double wmax, double zf, double zb, Color color, Color clipColor, boolean openingFace, boolean closingFace) { Object3D seg = new Object3D(color, true); seg.setProperty(Object3D.COLOR_PREFIX + "clip", clipColor); seg.addVertex(x0, y0b, zf); seg.addVertex(x0, y0b, zb); seg.addVertex(x0, y0t, zf); seg.addVertex(x0, y0t, zb); if (y1b >= wmax) { seg.addVertex(xpts[3], wmax, zf); seg.addVertex(xpts[3], wmax, zb); seg.addVertex(xpts[2], wmax, zf); seg.addVertex(xpts[2], wmax, zb); seg.addFace(new int[] {0, 2, 4, 6}); // front seg.addFace(new int[] {1, 7, 5, 3}); // rear seg.addFace(new int[] {2, 3, 5, 4}); // top seg.addFace(new int[] {4, 5, 7, 6}, "clip"); // clip top seg.addFace(new int[] {0, 6, 7, 1}); // bottom if (openingFace) { seg.addFace(new int[] {0, 1, 3, 2}); } // there is no closing face in this case return seg; } if (y1t > wmax) { if (y1b >= wmin) { seg.addVertex(xpts[3], wmax, zf); seg.addVertex(xpts[3], wmax, zb); seg.addVertex(x1, wmax, zf); seg.addVertex(x1, wmax, zb); seg.addVertex(x1, y1b, zf); seg.addVertex(x1, y1b, zb); seg.addFace(new int[] {0, 2, 4, 6, 8}); // front seg.addFace(new int[] {1, 9, 7, 5, 3}); // rear seg.addFace(new int[] {2, 3, 5, 4}); // top seg.addFace(new int[] {4, 5, 7, 6}, "clip"); // clip top seg.addFace(new int[] {0, 8, 9, 1}); if (openingFace) { seg.addFace(new int[] {0, 1, 3, 2}); } if (closingFace) { seg.addFace(new int[] {6, 7, 9, 8}); } return seg; } else { return null; // this case should not be possible } } if (y1t > wmin) { if (y1b >= wmin) { // this is the regular segment, no clipping seg.addVertex(x1, y1t, zf); seg.addVertex(x1, y1t, zb); seg.addVertex(x1, y1b, zf); seg.addVertex(x1, y1b, zb); seg.addFace(new int[] {0, 2, 4, 6}); // front seg.addFace(new int[] {1, 7, 5, 3}); // rear seg.addFace(new int[] {2, 3, 5, 4}); // top seg.addFace(new int[] {0, 6, 7, 1}); // bottom if (openingFace) { seg.addFace(new int[] {0, 1, 3, 2}); } if (closingFace) { seg.addFace(new int[] {4, 5, 7, 6}); } return seg; } else { seg.addVertex(x1, y1t, zf); seg.addVertex(x1, y1t, zb); seg.addVertex(x1, wmin, zf); seg.addVertex(x1, wmin, zb); seg.addVertex(xpts[0], wmin, zf); seg.addVertex(xpts[0], wmin, zb); seg.addFace(new int[] {0, 2, 4, 6, 8}); // front seg.addFace(new int[] {1, 9, 7, 5, 3}); // rear seg.addFace(new int[] {2, 3, 5, 4}); // top seg.addFace(new int[] {0, 8, 9, 1}); // bottom seg.addFace(new int[] {6, 7, 9, 8}, "clip"); // clip bottom if (openingFace) { seg.addFace(new int[] {0, 1, 3, 2}); } if (closingFace) { seg.addFace(new int[] {4, 5, 7, 6}); } return seg; } } else { seg.addVertex(xpts[1], wmin, zf); seg.addVertex(xpts[1], wmin, zb); seg.addVertex(xpts[0], wmin, zf); seg.addVertex(xpts[0], wmin, zb); seg.addFace(new int[] {0, 2, 4, 6}); // front seg.addFace(new int[] {1, 7, 5, 3}); // rear seg.addFace(new int[] {2, 3, 5, 4}); // top seg.addFace(new int[] {0, 6, 7, 1}); // bottom seg.addFace(new int[] {4, 5, 7, 6}, "clip"); // clip bottom if (openingFace) { seg.addFace(new int[] {0, 1, 3, 2}); } // there is no closing face in this case return seg; } } /** * Returns a segment for the case where the line height spans the lower * bound of the axis range at the left side of the chart. * * @param x0 * @param x1 * @param xpts * @param y0b * @param y0t * @param y1b * @param y1t * @param wmin * @param wmax * @param zf * @param zb * @param color * @param clipColor * @param openingFace * @param closingFace * * @return The segment. */ private Object3D createSegmentE(double x0, double x1, double[] xpts, double y0b, double y0t, double y1b, double y1t, double wmin, double wmax, double zf, double zb, Color color, Color clipColor, boolean openingFace, boolean closingFace) { if (y1b > wmax) { Object3D seg = new Object3D(color, true); seg.setProperty(Object3D.COLOR_PREFIX + "clip", clipColor); seg.addVertex(x0, wmin, zf); seg.addVertex(x0, wmin, zb); seg.addVertex(x0, y0t, zf); seg.addVertex(x0, y0t, zb); seg.addVertex(xpts[3], wmax, zf); seg.addVertex(xpts[3], wmax, zb); seg.addVertex(xpts[2], wmax, zf); seg.addVertex(xpts[2], wmax, zb); seg.addVertex(xpts[0], wmin, zf); seg.addVertex(xpts[0], wmin, zb); seg.addFace(new int[] {0, 2, 4, 6, 8}); // front seg.addFace(new int[] {1, 9, 7, 5, 3}); // rear seg.addFace(new int[] {2, 3, 5, 4}); // top seg.addFace(new int[] {4, 5, 7, 6}, "clip"); // clip top seg.addFace(new int[] {6, 7, 9, 8}); // bottom seg.addFace(new int[] {0, 8, 9, 1}, "clip"); // clip bottom if (openingFace) { seg.addFace(new int[] {0, 1, 3, 2}); } return seg; } if (y1t > wmax) { if (y1b >= wmin) { Object3D seg = new Object3D(color, true); seg.setProperty(Object3D.COLOR_PREFIX + "clip", clipColor); seg.addVertex(x0, wmin, zf); seg.addVertex(x0, wmin, zb); seg.addVertex(x0, y0t, zf); seg.addVertex(x0, y0t, zb); seg.addVertex(xpts[3], wmax, zf); seg.addVertex(xpts[3], wmax, zb); seg.addVertex(x1, wmax, zf); seg.addVertex(x1, wmax, zb); seg.addVertex(x1, y1b, zf); seg.addVertex(x1, y1b, zb); seg.addVertex(xpts[0], wmin, zf); seg.addVertex(xpts[0], wmin, zb); seg.addFace(new int[] {0, 2, 4, 6, 8, 10}); // front seg.addFace(new int[] {1, 11, 9, 7, 5, 3}); // rear seg.addFace(new int[] {2, 3, 5, 4}); // top seg.addFace(new int[] {5, 7, 6, 4}, "clip"); // clip top seg.addFace(new int[] {8, 9, 11, 10}); // bottom seg.addFace(new int[] {1, 0, 10, 11}, "clip"); if (openingFace) { seg.addFace(new int[] {0, 1, 3, 2}); } if (closingFace) { seg.addFace(new int[] {6, 7, 9, 8}); } return seg; } else { Object3D seg = new Object3D(color, true); seg.setProperty(Object3D.COLOR_PREFIX + "clip", clipColor); seg.addVertex(x0, wmin, zf); seg.addVertex(x0, wmin, zb); seg.addVertex(x0, y0t, zf); seg.addVertex(x0, y0t, zb); seg.addVertex(xpts[3], wmax, zf); seg.addVertex(xpts[3], wmax, zb); seg.addVertex(x1, wmax, zf); seg.addVertex(x1, wmax, zb); seg.addVertex(x1, wmin, zf); seg.addVertex(x1, wmin, zb); seg.addFace(new int[] {0, 2, 4, 6, 8}); // front seg.addFace(new int[] {1, 9, 7, 5, 3}); // rear seg.addFace(new int[] {2, 3, 5, 4}); // top seg.addFace(new int[] {5, 7, 6, 4}, "clip"); // clip top seg.addFace(new int[] {0, 8, 9, 1}, "clip"); // clip bottom if (openingFace) { seg.addFace(new int[] {0, 1, 3, 2}); } if (closingFace) { seg.addFace(new int[] {6, 7, 9, 8}); } return seg; } } if (y1t > wmin) { if (y1b >= wmin) { Object3D seg = new Object3D(color, true); seg.setProperty(Object3D.COLOR_PREFIX + "clip", clipColor); seg.addVertex(x0, wmin, zf); seg.addVertex(x0, wmin, zb); seg.addVertex(x0, y0t, zf); seg.addVertex(x0, y0t, zb); seg.addVertex(x1, y1t, zf); seg.addVertex(x1, y1t, zb); seg.addVertex(x1, y1b, zf); seg.addVertex(x1, y1b, zb); seg.addVertex(xpts[0], wmin, zf); seg.addVertex(xpts[0], wmin, zb); seg.addFace(new int[] {0, 2, 4, 6, 8}); // front seg.addFace(new int[] {1, 9, 7, 5, 3}); // rear seg.addFace(new int[] {2, 3, 5, 4}); // top seg.addFace(new int[] {6, 7, 9, 8}); // bottom seg.addFace(new int[] {0, 8, 9, 1}, "clip"); // clip bottom if (openingFace) { seg.addFace(new int[] {0, 1, 3, 2}); } if (closingFace) { seg.addFace(new int[] {4, 5, 7, 6}); } return seg; } else { Object3D seg = new Object3D(color, true); seg.setProperty(Object3D.COLOR_PREFIX + "clip", clipColor); seg.addVertex(x0, wmin, zf); seg.addVertex(x0, wmin, zb); seg.addVertex(x0, y0t, zf); seg.addVertex(x0, y0t, zb); seg.addVertex(x1, y1t, zf); seg.addVertex(x1, y1t, zb); seg.addVertex(x1, wmin, zf); seg.addVertex(x1, wmin, zb); seg.addFace(new int[] {0, 2, 4, 6}); // front seg.addFace(new int[] {1, 7, 5, 3}); // rear seg.addFace(new int[] {2, 3, 5, 4}); // top seg.addFace(new int[] {0, 6, 7, 1}, "clip"); // clip bottom if (openingFace) { seg.addFace(new int[] {0, 1, 3, 2}); } if (closingFace) { seg.addFace(new int[] {4, 5, 7, 6}); } return seg; } } Object3D seg = new Object3D(color, true); seg.setProperty(Object3D.COLOR_PREFIX + "clip", clipColor); seg.addVertex(x0, wmin, zf); seg.addVertex(x0, wmin, zb); seg.addVertex(x0, y0t, zf); seg.addVertex(x0, y0t, zb); seg.addVertex(xpts[1], wmin, zf); seg.addVertex(xpts[1], wmin, zb); seg.addFace(new int[] {0, 2, 4}); // front seg.addFace(new int[] {1, 5, 3}); // rear seg.addFace(new int[] {2, 3, 5, 4}); // top seg.addFace(new int[] {0, 4, 5, 1}, "clip"); // clip bottom if (openingFace) { seg.addFace(new int[] {0, 1, 3, 2}); } // there is no closing face in this case return seg; } /** * Creates and returns a segment for the case where the line is completely * below the axis range at the left side. * * @param x0 * @param x1 * @param xpts * @param y0b * @param y0t * @param y1b * @param y1t * @param wmin * @param wmax * @param zf * @param zb * @param color * @param clipColor * @param openingFace ignored because there is no opening face in this * case. * @param closingFace * * @return A segment. */ private Object3D createSegmentF(double x0, double x1, double[] xpts, double y0b, double y0t, double y1b, double y1t, double wmin, double wmax, double zf, double zb, Color color, Color clipColor, boolean openingFace, boolean closingFace) { if (y1b > wmax) { Object3D seg = new Object3D(color, true); seg.setProperty(Object3D.COLOR_PREFIX + "clip", clipColor); seg.addVertex(xpts[1], wmin, zf); seg.addVertex(xpts[1], wmin, zb); seg.addVertex(xpts[3], wmax, zf); seg.addVertex(xpts[3], wmax, zb); seg.addVertex(xpts[2], wmax, zf); seg.addVertex(xpts[2], wmax, zb); seg.addVertex(xpts[0], wmin, zf); seg.addVertex(xpts[0], wmin, zb); seg.addFace(new int[] {0, 2, 4, 6}); // front seg.addFace(new int[] {1, 7, 5, 3}); // rear seg.addFace(new int[] {0, 1, 3, 2}); // top seg.addFace(new int[] {2, 3, 5, 4}, "clip"); // clip top seg.addFace(new int[] {4, 5, 7, 6}); // bottom seg.addFace(new int[] {0, 6, 7, 1}, "clip"); // clip bottom // there are no opening and closing faces for this case return seg; } if (y1t > wmax) { if (y1b > wmin) { Object3D seg = new Object3D(color, true); seg.setProperty(Object3D.COLOR_PREFIX + "clip", clipColor); seg.addVertex(xpts[1], wmin, zf); seg.addVertex(xpts[1], wmin, zb); seg.addVertex(xpts[3], wmax, zf); seg.addVertex(xpts[3], wmax, zb); seg.addVertex(x1, wmax, zf); seg.addVertex(x1, wmax, zb); seg.addVertex(x1, y1b, zf); seg.addVertex(x1, y1b, zb); seg.addVertex(xpts[0], wmin, zf); seg.addVertex(xpts[0], wmin, zb); seg.addFace(new int[] {0, 2, 4, 6, 8}); // front seg.addFace(new int[] {1, 9, 7, 5, 3}); // rear seg.addFace(new int[] {2, 3, 5, 4}); //clip top seg.addFace(new int[] {0, 1, 3, 2}); // top seg.addFace(new int[] {0, 8, 9, 1}, "clip"); // clip bottom seg.addFace(new int[] {6, 7, 9, 8}); // bottom // there is no opening face in this case if (closingFace) { seg.addFace(new int[] {4, 5, 7, 6}); } return seg; } else { Object3D seg = new Object3D(color, true); seg.setProperty(Object3D.COLOR_PREFIX + "clip", clipColor); seg.addVertex(xpts[1], wmin, zf); seg.addVertex(xpts[1], wmin, zb); seg.addVertex(xpts[3], wmax, zf); seg.addVertex(xpts[3], wmax, zb); seg.addVertex(x1, wmax, zf); seg.addVertex(x1, wmax, zb); seg.addVertex(x1, wmin, zf); seg.addVertex(x1, wmin, zb); seg.addFace(new int[] {0, 2, 4, 6}); // front seg.addFace(new int[] {1, 7, 5, 3}); // rear seg.addFace(new int[] {0, 1, 3, 2}); // top seg.addFace(new int[] {2, 3, 5, 4}, "clip"); // clip top seg.addFace(new int[] {6, 7, 1, 0}, "clip"); // clip bottom if (closingFace) { seg.addFace(new int[] {4, 5, 7, 6}); } return seg; } } if (y1t > wmin) { if (y1b >= wmin) { Object3D seg = new Object3D(color, true); seg.setProperty(Object3D.COLOR_PREFIX + "clip", clipColor); seg.addVertex(xpts[1], wmin, zf); seg.addVertex(xpts[1], wmin, zb); seg.addVertex(x1, y1t, zf); seg.addVertex(x1, y1t, zb); seg.addVertex(x1, y1b, zf); seg.addVertex(x1, y1b, zb); seg.addVertex(xpts[0], wmin, zf); seg.addVertex(xpts[0], wmin, zb); seg.addFace(new int[] {0, 2, 4, 6}); // front seg.addFace(new int[] {1, 7, 5, 3}); // rear seg.addFace(new int[] {0, 1, 3, 2}); // top seg.addFace(new int[] {4, 5, 7, 6}); // bottom seg.addFace(new int[] {0, 6, 7, 1}, "clip"); // clip bottom if (closingFace) { seg.addFace(new int[] {2, 3, 5, 4}); } return seg; } else { Object3D seg = new Object3D(color, true); seg.setProperty(Object3D.COLOR_PREFIX + "clip", clipColor); seg.addVertex(xpts[1], wmin, zf); seg.addVertex(xpts[1], wmin, zb); seg.addVertex(x1, y1t, zf); seg.addVertex(x1, y1t, zb); seg.addVertex(x1, wmin, zf); seg.addVertex(x1, wmin, zb); seg.addFace(new int[] {0, 2, 4}); // front seg.addFace(new int[] {1, 5, 3}); // rear seg.addFace(new int[] {0, 1, 3, 2}); // top seg.addFace(new int[] {0, 4, 5, 1}, "clip"); // clip bottom // there is no opening face in this case if (closingFace) { seg.addFace(new int[] {2, 3, 5, 4}); } return seg; } } return null; // nothing to see } /** * Tests this renderer for equality with an arbitrary object. * * @param obj the object ({@code null} not permitted). * * @return A boolean. */ @Override public boolean equals(Object obj) { if (obj == this) { return true; } if (!(obj instanceof LineRenderer3D)) { return false; } LineRenderer3D that = (LineRenderer3D) obj; if (this.lineWidth != that.lineWidth) { return false; } if (this.lineHeight != that.lineHeight) { return false; } if (this.isolatedItemWidthPercent != that.isolatedItemWidthPercent) { return false; } if (!ObjectUtils.equals(this.clipColorSource, that.clipColorSource)) { return false; } return super.equals(obj); } } orson-charts-2.1.0/src/main/java/org/jfree/chart3d/renderer/category/StackedBarRenderer3D.java000066400000000000000000000204451417331271500321620ustar00rootroot00000000000000/* =========================================================== * Orson Charts : a 3D chart library for the Java(tm) platform * =========================================================== * * (C)opyright 2013-2022, by David Gilbert. All rights reserved. * * https://github.com/jfree/orson-charts * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . * * [Oracle and Java are registered trademarks of Oracle and/or its affiliates. * Other names may be trademarks of their respective owners.] * * If you do not wish to be bound by the terms of the GPL, an alternative * commercial license can be purchased. For details, please see visit the * Orson Charts home page: * * http://www.object-refinery.com/orsoncharts/index.html * */ package org.jfree.chart3d.renderer.category; import org.jfree.chart3d.Chart3DFactory; import org.jfree.chart3d.data.DataUtils; import org.jfree.chart3d.data.KeyedValues3DItemKey; import org.jfree.chart3d.data.Range; import org.jfree.chart3d.data.Values3D; import org.jfree.chart3d.data.category.CategoryDataset3D; import org.jfree.chart3d.graphics3d.Dimension3D; import org.jfree.chart3d.graphics3d.Object3D; import org.jfree.chart3d.graphics3d.Offset3D; import org.jfree.chart3d.graphics3d.World; import org.jfree.chart3d.label.ItemLabelPositioning; import org.jfree.chart3d.plot.CategoryPlot3D; /** * A renderer that can be used with the {@link CategoryPlot3D} class to create * 3D stacked bar charts from data in a {@link CategoryDataset3D}. The * {@code createStackedBarChart()} method in the {@link Chart3DFactory} * class will construct a chart that uses this renderer. Here is a sample: *
* StackedBarChart3DDemo1.svg *
* (refer to {@code StackedBarChart3DDemo1.java} for the code to generate * the above chart). *

* There is a factory method to create a chart using this renderer - see * {@link Chart3DFactory#createStackedBarChart(String, String, CategoryDataset3D, String, String, String)}. *

* NOTE: This class is serializable, but the serialization format is subject * to change in future releases and should not be relied upon for persisting * instances of this class. */ @SuppressWarnings("serial") public class StackedBarRenderer3D extends BarRenderer3D { /** * Creates a default constructor. */ public StackedBarRenderer3D() { super(); setItemLabelPositioning(ItemLabelPositioning.FRONT_AND_BACK); setItemLabelOffsets(new Offset3D(0.0, 0.0, -1.0)); } /** * Returns the range of values that will be required on the value axis * to see all the data from the dataset. We override the method to * account for the bars from each series being stacked on top of one * another. * * @param data the data ({@code null} not permitted). * * @return The range (possibly {@code null}) */ @Override public Range findValueRange(Values3D data) { return DataUtils.findStackedValueRange(data); } /** * Constructs and places one item from the specified dataset into the given * world. This method will be called by the {@link CategoryPlot3D} class * while iterating over the items in the dataset. * * @param dataset the dataset ({@code null} not permitted). * @param series the series index. * @param row the row index. * @param column the column index. * @param world the world ({@code null} not permitted). * @param dimensions the plot dimensions ({@code null} not permitted). * @param xOffset the x-offset. * @param yOffset the y-offset. * @param zOffset the z-offset. */ @Override @SuppressWarnings("unchecked") public void composeItem(CategoryDataset3D dataset, int series, int row, int column, World world, Dimension3D dimensions, double xOffset, double yOffset, double zOffset) { double value = dataset.getDoubleValue(series, row, column); if (Double.isNaN(value)) { return; } double[] stack = DataUtils.stackSubTotal(dataset, getBase(), series, row, column); double lower = stack[1]; if (value < 0.0) { lower = stack[0]; } double upper = lower + value; composeItem(upper, lower, dataset, series, row, column, world, dimensions, xOffset, yOffset, zOffset); } /** * Draws the item labels. * * @param world the world. * @param dataset the dataset. * @param itemKey the item key. * @param xw the x-coordinate. * @param yw the y-coordinate. * @param zw the z-coordinate. * @param basew the base coordinate. * @param inverted is the y-axis inverted? */ @Override protected void drawItemLabels(World world, CategoryDataset3D dataset, KeyedValues3DItemKey itemKey, double xw, double yw, double zw, double basew, boolean inverted) { ItemLabelPositioning positioning = getItemLabelPositioning(); if (getItemLabelGenerator() != null) { String label = getItemLabelGenerator().generateItemLabel(dataset, itemKey.getSeriesKey(), itemKey.getRowKey(), itemKey.getColumnKey()); if (label != null) { Dimension3D dimensions = getPlot().getDimensions(); double dx = getItemLabelOffsets().getDX(); double dy = getItemLabelOffsets().getDY() * dimensions.getHeight(); double dz = getItemLabelOffsets().getDZ() * getBarZWidth(); if (positioning.equals(ItemLabelPositioning.CENTRAL)) { double yy = yw; if (inverted) { yy = basew; dy = -dy; } Object3D labelObj = Object3D.createLabelObject(label, getItemLabelFont(), getItemLabelColor(), getItemLabelBackgroundColor(), xw + dx, yy + dy, zw, false, true); labelObj.setProperty(Object3D.ITEM_KEY, itemKey); world.add(labelObj); } else if (positioning.equals( ItemLabelPositioning.FRONT_AND_BACK)) { double yy = (yw + basew) / 2.0; Object3D labelObj1 = Object3D.createLabelObject(label, getItemLabelFont(), getItemLabelColor(), getItemLabelBackgroundColor(), xw + dx, yy + dy, zw + dz, false, false); labelObj1.setProperty(Object3D.ITEM_KEY, itemKey); world.add(labelObj1); Object3D labelObj2 = Object3D.createLabelObject(label, getItemLabelFont(), getItemLabelColor(), getItemLabelBackgroundColor(), xw + dx, yy + dy, zw - dz, true, false); labelObj2.setProperty(Object3D.ITEM_KEY, itemKey); world.add(labelObj2); } } } } /** * Tests this renderer for equality with an arbitrary object. * * @param obj the object ({@code null} permitted). * * @return A boolean. */ @Override public boolean equals(Object obj) { if (obj == this) { return true; } if (!(obj instanceof StackedBarRenderer3D)) { return false; } return super.equals(obj); } }StandardCategoryColorSource.java000066400000000000000000000122621417331271500336360ustar00rootroot00000000000000orson-charts-2.1.0/src/main/java/org/jfree/chart3d/renderer/category/* =========================================================== * Orson Charts : a 3D chart library for the Java(tm) platform * =========================================================== * * (C)opyright 2013-2022, by David Gilbert. All rights reserved. * * https://github.com/jfree/orson-charts * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . * * [Oracle and Java are registered trademarks of Oracle and/or its affiliates. * Other names may be trademarks of their respective owners.] * * If you do not wish to be bound by the terms of the GPL, an alternative * commercial license can be purchased. For details, please see visit the * Orson Charts home page: * * http://www.object-refinery.com/orsoncharts/index.html * */ package org.jfree.chart3d.renderer.category; import java.awt.Color; import java.io.Serializable; import java.util.Arrays; import org.jfree.chart3d.Colors; import org.jfree.chart3d.internal.Args; /** * A standard implementation of the {@link CategoryColorSource} interface. *

* NOTE: This class is serializable, but the serialization format is subject * to change in future releases and should not be relied upon for persisting * instances of this class. */ @SuppressWarnings("serial") public class StandardCategoryColorSource implements CategoryColorSource, Serializable { /** The sequence of color objects to use for each series. */ private Color[] colors; /** * Creates a new instance with default colors. */ public StandardCategoryColorSource() { this(Colors.getDefaultColors()); } /** * Creates a new instance with the supplied sequence of colors. The * supplied array must have at least one entry, and all entries must be * non-{@code null}. * * @param colors the colors ({@code null} not permitted). */ public StandardCategoryColorSource(Color... colors) { Args.nullNotPermitted(colors, "colors"); if (colors.length == 0) { throw new IllegalArgumentException( "Zero length array not permitted."); } for (Color c: colors) { if (c == null) { throw new IllegalArgumentException( "Null array entries not permitted."); } } this.colors = colors.clone(); } /** * Returns the color to use for the specified item. * * @param series the series index. * @param row the row index. * @param column the column index. * * @return The color (never {@code null}). */ @Override public Color getColor(int series, int row, int column) { return this.colors[series % this.colors.length]; } /** * Returns the color to use in the legend for the specified series. * * @param series the series index. * * @return The color (never {@code null}). */ @Override public Color getLegendColor(int series) { return this.colors[series % this.colors.length]; } /** * Restyles the source using the specified colors. Refer to the * implementing class to confirm the precise behaviour (typically all * existing color settings are cleared and the specified colors are * installed as the new defaults). * * @param colors the colors. * * @since 1.2 */ @Override public void style(Color... colors) { Args.nullNotPermitted(colors, "colors"); if (colors.length == 0) { throw new IllegalArgumentException( "Zero length array not permitted."); } for (Color c: colors) { if (c == null) { throw new IllegalArgumentException( "Null array entries not permitted."); } } this.colors = colors.clone(); } /** * Tests this color source for equality with an arbitrary object. * * @param obj the object ({@code null} permitted). * * @return A boolean. */ @Override public boolean equals(Object obj) { if (obj == this) { return true; } if (!(obj instanceof StandardCategoryColorSource)) { return false; } StandardCategoryColorSource that = (StandardCategoryColorSource) obj; if (!Arrays.equals(this.colors, that.colors)) { return false; } return true; } @Override public int hashCode() { int hash = 7; hash = 97 * hash + Arrays.deepHashCode(this.colors); return hash; } }orson-charts-2.1.0/src/main/java/org/jfree/chart3d/renderer/category/package-info.java000066400000000000000000000002251417331271500306170ustar00rootroot00000000000000/** * Renderers that can be used with the * {@link org.jfree.chart3d.plot.CategoryPlot3D} class. */ package org.jfree.chart3d.renderer.category; orson-charts-2.1.0/src/main/java/org/jfree/chart3d/renderer/package-info.java000066400000000000000000000001221417331271500267760ustar00rootroot00000000000000/** * Base package for renderer support. */ package org.jfree.chart3d.renderer; orson-charts-2.1.0/src/main/java/org/jfree/chart3d/renderer/xyz/000077500000000000000000000000001417331271500244465ustar00rootroot00000000000000orson-charts-2.1.0/src/main/java/org/jfree/chart3d/renderer/xyz/AbstractXYZRenderer.java000066400000000000000000000201651417331271500311620ustar00rootroot00000000000000/* =========================================================== * Orson Charts : a 3D chart library for the Java(tm) platform * =========================================================== * * (C)opyright 2013-2022, by David Gilbert. All rights reserved. * * https://github.com/jfree/orson-charts * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . * * [Oracle and Java are registered trademarks of Oracle and/or its affiliates. * Other names may be trademarks of their respective owners.] * * If you do not wish to be bound by the terms of the GPL, an alternative * commercial license can be purchased. For details, please see visit the * Orson Charts home page: * * http://www.object-refinery.com/orsoncharts/index.html * */ package org.jfree.chart3d.renderer.xyz; import java.awt.Color; import org.jfree.chart3d.data.DataUtils; import org.jfree.chart3d.data.Range; import org.jfree.chart3d.data.xyz.XYZDataset; import org.jfree.chart3d.graphics3d.Dimension3D; import org.jfree.chart3d.graphics3d.World; import org.jfree.chart3d.internal.Args; import org.jfree.chart3d.internal.ObjectUtils; import org.jfree.chart3d.label.XYZItemLabelGenerator; import org.jfree.chart3d.plot.XYZPlot; import org.jfree.chart3d.renderer.AbstractRenderer3D; import org.jfree.chart3d.renderer.ComposeType; import org.jfree.chart3d.renderer.Renderer3DChangeEvent; /** * An abstract base class that can be used to create new {@link XYZRenderer} * subclasses. */ public class AbstractXYZRenderer extends AbstractRenderer3D { private XYZPlot plot; private XYZColorSource colorSource; /** * An object that generates item labels for the chart. Can be null. */ private XYZItemLabelGenerator itemLabelGenerator; /** * Creates a new default instance. */ protected AbstractXYZRenderer() { this.colorSource = new StandardXYZColorSource(); this.itemLabelGenerator = null; } /** * Returns the plot that the renderer is assigned to, if any. * * @return The plot (possibly {@code null}). */ public XYZPlot getPlot() { return this.plot; } /** * Sets the plot that the renderer is assigned to. * * @param plot the plot ({@code null} permitted). */ public void setPlot(XYZPlot plot) { this.plot = plot; } /** * Returns the item label generator for the renderer. The default value * is {@code null}. Not all subclasses will use this generator * (for example, the {@link SurfaceRenderer} does not display item labels). * * @return The item label generator (possibly {@code null}). * * @since 1.3 */ public XYZItemLabelGenerator getItemLabelGenerator() { return this.itemLabelGenerator; } /** * Sets the item label generator and sends a change event to all registered * listeners. You can set this to {@code null} in which case no * item labels will be generated. * * @param generator the new generator ({@code null} permitted). * * @since 1.3 */ public void setItemLabelGenerator(XYZItemLabelGenerator generator) { this.itemLabelGenerator = generator; } /** * Returns the type of composition performed by this renderer. The default * is {@code PER_ITEM} which means the plot will ask the renderer * to compose one data item at a time into the 3D model. Some renderers * will override this method to return {@code ALL}, which means the * renderer will compose all of the data items in one go (the plot calls * the {@link #composeAll(XYZPlot, World, Dimension3D, double, double, double)} * method to trigger this). * * @return The compose type (never {@code null}). * * @since 1.1 */ public ComposeType getComposeType() { return ComposeType.PER_ITEM; } /** * Adds objects to the {@code world} to represent all the data items * that this renderer is responsible for. This method is only called for * renderers that return {@link ComposeType#ALL} from the * {@link #getComposeType()} method. * * @param plot the plot (not {@code null}). * @param world the 3D model (not {@code null}). * @param dimensions the dimensions of the plot (not {@code null}). * @param xOffset the x-offset. * @param yOffset the y-offset. * @param zOffset the z-offset. */ public void composeAll(XYZPlot plot, World world, Dimension3D dimensions, double xOffset, double yOffset, double zOffset) { throw new UnsupportedOperationException(); } /** * Returns the object that provides the color instances for items drawn * by the renderer. * * @return The color source (never {@code null}). */ public XYZColorSource getColorSource() { return this.colorSource; } /** * Sets the color source and sends a {@link Renderer3DChangeEvent} to all * registered listeners. * * @param colorSource the color source ({@code null} not permitted). */ public void setColorSource(XYZColorSource colorSource) { Args.nullNotPermitted(colorSource, "colorSource"); this.colorSource = colorSource; fireChangeEvent(true); } /** * Sets a new color source for the renderer using the specified colors and * sends a {@link Renderer3DChangeEvent} to all registered listeners. This * is a convenience method that is equivalent to * {@code setColorSource(new StandardXYZColorSource(colors))}. * * @param colors one or more colors ({@code null} not permitted). * * @since 1.1 */ public void setColors(Color... colors) { setColorSource(new StandardXYZColorSource(colors)); } /** * Returns the range that is required on the x-axis for this renderer * to display all the items in the specified dataset. * * @param dataset the dataset ({@code null} not permitted). * * @return The x-range. */ public Range findXRange(XYZDataset dataset) { return DataUtils.findXRange(dataset); } /** * Returns the range that is required on the y-axis for this renderer * to display all the items in the specified dataset. * * @param dataset the dataset ({@code null} not permitted). * * @return The y-range. */ public Range findYRange(XYZDataset dataset) { return DataUtils.findYRange(dataset); } /** * Returns the range that is required on the z-axis for this renderer * to display all the items in the specified dataset. * * @param dataset the dataset ({@code null} not permitted). * * @return The z-range. */ public Range findZRange(XYZDataset dataset) { return DataUtils.findZRange(dataset); } /** * Tests this renderer for equality with an arbitrary object. * * @param obj the object ({@code null} permitted). * * @return A boolean. */ @Override public boolean equals(Object obj) { if (obj == this) { return true; } if (!(obj instanceof AbstractXYZRenderer)) { return false; } AbstractXYZRenderer that = (AbstractXYZRenderer) obj; if (!this.colorSource.equals(that.colorSource)) { return false; } if (!ObjectUtils.equals(this.itemLabelGenerator, that.itemLabelGenerator)) { return false; } return super.equals(obj); } } orson-charts-2.1.0/src/main/java/org/jfree/chart3d/renderer/xyz/BarXYZRenderer.java000066400000000000000000000327521417331271500301300ustar00rootroot00000000000000/* =========================================================== * Orson Charts : a 3D chart library for the Java(tm) platform * =========================================================== * * (C)opyright 2013-2022, by David Gilbert. All rights reserved. * * https://github.com/jfree/orson-charts * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . * * [Oracle and Java are registered trademarks of Oracle and/or its affiliates. * Other names may be trademarks of their respective owners.] * * If you do not wish to be bound by the terms of the GPL, an alternative * commercial license can be purchased. For details, please see visit the * Orson Charts home page: * * http://www.object-refinery.com/orsoncharts/index.html * */ package org.jfree.chart3d.renderer.xyz; import java.awt.Color; import java.io.Serializable; import org.jfree.chart3d.axis.Axis3D; import org.jfree.chart3d.data.DataUtils; import org.jfree.chart3d.data.Range; import org.jfree.chart3d.data.xyz.XYZDataset; import org.jfree.chart3d.graphics3d.Dimension3D; import org.jfree.chart3d.graphics3d.Object3D; import org.jfree.chart3d.graphics3d.World; import org.jfree.chart3d.internal.ObjectUtils; import org.jfree.chart3d.plot.XYZPlot; import org.jfree.chart3d.renderer.Renderer3DChangeEvent; /** * A renderer that draws 3D bars on an {@link XYZPlot} using data from an * {@link XYZDataset}. Here is a sample: *
* XYZBarChart3DDemo1.svg *
* (refer to {@code XYZBarChart3DDemo1.java} for the code to generate * the above chart). *

* NOTE: This class is serializable, but the serialization format is subject * to change in future releases and should not be relied upon for persisting * instances of this class. */ @SuppressWarnings("serial") public class BarXYZRenderer extends AbstractXYZRenderer implements XYZRenderer, Serializable { /** The base value (normally 0.0, but can be modified). */ private double base; /** The width of the bars along the x-axis. */ private double barXWidth; /** The width of the bars along the z-axis. */ private double barZWidth; /** * The color source used to fetch the color for the base of bars where * the actual base of the bar is *outside* of the current axis range * (that is, the bar is "cropped"). If this is {@code null}, then * the regular bar color is used. */ private XYZColorSource baseColorSource; /** * The color source used to fetch the color for the top of bars where * the actual top of the bar is *outside* of the current axis range * (that is, the bar is "cropped"). If this is {@code null} then the * bar top is always drawn using the series paint. */ private XYZColorSource topColorSource; /** * Creates a new default instance. */ public BarXYZRenderer() { this.base = 0.0; this.barXWidth = 0.8; this.barZWidth = 0.8; this.baseColorSource = new StandardXYZColorSource(Color.WHITE); this.topColorSource = new StandardXYZColorSource(Color.BLACK); } /** * Returns the value for the base of the bars. The default is * {@code 0.0}. * * @return The value for the base of the bars. */ public double getBase() { return this.base; } /** * Sets the base value for the bars and sends a * {@link Renderer3DChangeEvent} to all registered listeners. * * @param base the base. */ public void setBase(double base) { this.base = base; fireChangeEvent(true); } /** * Returns the width of the bars in the direction of the x-axis, in the * units of the x-axis. The default value is {@code 0.8}. * * @return The width of the bars. */ public double getBarXWidth() { return this.barXWidth; } /** * Sets the width of the bars in the direction of the x-axis and sends a * {@link Renderer3DChangeEvent} to all registered listeners. * * @param width the width. */ public void setBarXWidth(double width) { this.barXWidth = width; fireChangeEvent(true); } /** * Returns the width of the bars in the direction of the z-axis, in the * units of the z-axis. The default value is {@code 0.8}. * * @return The width of the bars. */ public double getBarZWidth() { return this.barZWidth; } /** * Sets the width of the bars in the direction of the z-axis and sends a * {@link Renderer3DChangeEvent} to all registered listeners. * * @param width the width. */ public void setBarZWidth(double width) { this.barZWidth = width; fireChangeEvent(true); } /** * Returns the object used to fetch the color for the base of bars * where the base of the bar is "cropped" (on account of the base value * falling outside of the bounds of the y-axis). This is used to give a * visual indication to the end-user that the bar on display is cropped. * If this paint source is {@code null}, the regular series color * will be used for the top of the bars. * * @return A paint source (possibly {@code null}). */ public XYZColorSource getBaseColorSource() { return this.baseColorSource; } /** * Sets the object that determines the color to use for the base of bars * where the base value falls outside the axis range, and sends a * {@link Renderer3DChangeEvent} to all registered listeners. If you set * this to {@code null}, the regular series color will be used to draw * the base of the bar, but it will be harder for the end-user to know that * only a section of the bar is visible in the chart. Note that the * default base paint source returns {@code Color.WHITE} always. * * @param source the source ({@code null} permitted). * * @see #getBaseColorSource() * @see #getTopColorSource() */ public void setBaseColorSource(XYZColorSource source) { this.baseColorSource = source; fireChangeEvent(true); } /** * Returns the object used to fetch the color for the top of bars * where the top of the bar is "cropped" (on account of the data value * falling outside of the bounds of the y-axis). This is used to give a * visual indication to the end-user that the bar on display is cropped. * If this paint source is {@code null}, the regular series color * will be used for the top of the bars. * * @return A paint source (possibly {@code null}). */ public XYZColorSource getTopColorSource() { return this.topColorSource; } /** * Sets the object used to fetch the color for the top of bars where the * top of the bar is "cropped", and sends a {@link Renderer3DChangeEvent} * to all registered listeners. * * @param source the source ({@code null} permitted). * * @see #getTopColorSource() * @see #getBaseColorSource() */ public void setTopColorSource(XYZColorSource source) { this.topColorSource = source; fireChangeEvent(true); } /** * Returns the range that needs to be set on the x-axis in order for this * renderer to be able to display all the data in the supplied dataset. * * @param dataset the dataset ({@code null} not permitted). * * @return The range ({@code null} if there is no data in the dataset). */ @Override public Range findXRange(XYZDataset dataset) { // delegate argument check... Range xRange = DataUtils.findXRange(dataset); if (xRange == null) { return null; } double delta = this.barXWidth / 2.0; return new Range(xRange.getMin() - delta, xRange.getMax() + delta); } /** * Returns the range to use for the y-axis to ensure that all data values * are visible on the chart. This method is overridden to ensure that the * base value is included. * * @param dataset the dataset ({@code null} not permitted). * * @return The range ({@code null} when there is no data). */ @Override public Range findYRange(XYZDataset dataset) { return DataUtils.findYRange(dataset, this.base); } /** * Returns the range to use for the z-axis to ensure that all data values * are visible on the chart. This method is overridden to account for the * bar widths. * * @param dataset the dataset ({@code null} not permitted). * * @return The range ({@code null} when there is no data). */ @Override public Range findZRange(XYZDataset dataset) { Range zRange = DataUtils.findZRange(dataset); if (zRange == null) { return null; } double delta = this.barZWidth / 2.0; return new Range(zRange.getMin() - delta, zRange.getMax() + delta); } /** * Adds a single bar representing one item from the dataset. * * @param dataset the dataset. * @param series the series index. * @param item the item index. * @param world the world used to model the 3D chart. * @param dimensions the plot dimensions in 3D. * @param xOffset the x-offset. * @param yOffset the y-offset. * @param zOffset the z-offset. */ @Override public void composeItem(XYZDataset dataset, int series, int item, World world, Dimension3D dimensions, double xOffset, double yOffset, double zOffset) { XYZPlot plot = getPlot(); Axis3D xAxis = plot.getXAxis(); Axis3D yAxis = plot.getYAxis(); Axis3D zAxis = plot.getZAxis(); double x = dataset.getX(series, item); double y = dataset.getY(series, item); double z = dataset.getZ(series, item); double xdelta = this.barXWidth / 2.0; double zdelta = this.barZWidth / 2.0; double x0 = xAxis.getRange().peggedValue(x - xdelta); double x1 = xAxis.getRange().peggedValue(x + xdelta); double z0 = zAxis.getRange().peggedValue(z - zdelta); double z1 = zAxis.getRange().peggedValue(z + zdelta); if ((x1 <= x0) || (z1 <= z0)) { return; } double ylow = Math.min(this.base, y); double yhigh = Math.max(this.base, y); Range range = yAxis.getRange(); if (!range.intersects(ylow, yhigh)) { return; // the bar is not visible for the given axis range } double ybase = range.peggedValue(ylow); double ytop = range.peggedValue(yhigh); boolean inverted = this.base > y; double wx0 = xAxis.translateToWorld(x0, dimensions.getWidth()); double wx1 = xAxis.translateToWorld(x1, dimensions.getWidth()); double wy0 = yAxis.translateToWorld(ybase, dimensions.getHeight()); double wy1 = yAxis.translateToWorld(ytop, dimensions.getHeight()); double wz0 = zAxis.translateToWorld(z0, dimensions.getDepth()); double wz1 = zAxis.translateToWorld(z1, dimensions.getDepth()); Color color = getColorSource().getColor(series, item); Color baseColor = null; if (this.baseColorSource != null && !range.contains(this.base)) { baseColor = this.baseColorSource.getColor(series, item); } if (baseColor == null) { baseColor = color; } Color topColor = null; if (this.topColorSource != null && !range.contains(y)) { topColor = this.topColorSource.getColor(series, item); } if (topColor == null) { topColor = color; } Object3D bar = Object3D.createBar(wx1 - wx0, wz1 - wz0, ((wx0 + wx1) / 2.0) + xOffset, wy1 + yOffset, ((wz0 + wz1) / 2.0) + zOffset, wy0 + yOffset, color, baseColor, topColor, inverted); world.add(bar); } /** * Tests this renderer for equality with an arbitrary object. * * @param obj the object ({@code null} permitted). * * @return A boolean. */ @Override public boolean equals(Object obj) { if (obj == this) { return true; } if (!(obj instanceof BarXYZRenderer)) { return false; } BarXYZRenderer that = (BarXYZRenderer) obj; if (this.base != that.base) { return false; } if (this.barXWidth != that.barXWidth) { return false; } if (this.barZWidth != that.barZWidth) { return false; } if (!ObjectUtils.equals(this.baseColorSource, that.baseColorSource)) { return false; } if (!ObjectUtils.equals(this.topColorSource, that.topColorSource)) { return false; } return super.equals(obj); } } orson-charts-2.1.0/src/main/java/org/jfree/chart3d/renderer/xyz/LineXYZRenderer.java000066400000000000000000000126261417331271500303110ustar00rootroot00000000000000/* =========================================================== * Orson Charts : a 3D chart library for the Java(tm) platform * =========================================================== * * (C)opyright 2013-2022, by David Gilbert. All rights reserved. * * https://github.com/jfree/orson-charts * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . * * [Oracle and Java are registered trademarks of Oracle and/or its affiliates. * Other names may be trademarks of their respective owners.] * * If you do not wish to be bound by the terms of the GPL, an alternative * commercial license can be purchased. For details, please see visit the * Orson Charts home page: * * http://www.object-refinery.com/orsoncharts/index.html * */ package org.jfree.chart3d.renderer.xyz; import java.awt.Color; import java.io.Serializable; import org.jfree.chart3d.axis.Axis3D; import org.jfree.chart3d.data.xyz.XYZDataset; import org.jfree.chart3d.graphics3d.Dimension3D; import org.jfree.chart3d.graphics3d.Line3D; import org.jfree.chart3d.graphics3d.LineObject3D; import org.jfree.chart3d.graphics3d.World; import org.jfree.chart3d.plot.XYZPlot; /** * A renderer that draws 3D lines on an {@link XYZPlot} using data from an * {@link XYZDataset}. Here is a sample: *
* XYZLineChart3DDemo1.svg *
* (refer to {@code XYZLineChart3DDemo1.java} for the code to generate * the above chart). *

* NOTE: This class is serializable, but the serialization format is subject * to change in future releases and should not be relied upon for persisting * instances of this class. * * @since 1.5 */ @SuppressWarnings("serial") public class LineXYZRenderer extends AbstractXYZRenderer implements XYZRenderer, Serializable { /** * Creates a new default instance. */ public LineXYZRenderer() { } /** * Adds a single line representing one item from the dataset. * * @param dataset the dataset. * @param series the series index. * @param item the item index. * @param world the world used to model the 3D chart. * @param dimensions the plot dimensions in 3D. * @param xOffset the x-offset. * @param yOffset the y-offset. * @param zOffset the z-offset. */ @Override public void composeItem(XYZDataset dataset, int series, int item, World world, Dimension3D dimensions, double xOffset, double yOffset, double zOffset) { if (item == 0) { // we are connecting lines between points, so there return; // is nothing to do for item 0 } XYZPlot plot = getPlot(); Axis3D xAxis = plot.getXAxis(); Axis3D yAxis = plot.getYAxis(); Axis3D zAxis = plot.getZAxis(); double x1 = dataset.getX(series, item); double y1 = dataset.getY(series, item); double z1 = dataset.getZ(series, item); double x0 = dataset.getX(series, item - 1); double y0 = dataset.getY(series, item - 1); double z0 = dataset.getZ(series, item - 1); double wx0 = xAxis.translateToWorld(x0, dimensions.getWidth()); double wx1 = xAxis.translateToWorld(x1, dimensions.getWidth()); double wy0 = yAxis.translateToWorld(y0, dimensions.getHeight()); double wy1 = yAxis.translateToWorld(y1, dimensions.getHeight()); double wz0 = zAxis.translateToWorld(z0, dimensions.getDepth()); double wz1 = zAxis.translateToWorld(z1, dimensions.getDepth()); Line3D line = new Line3D(wx0, wy0, wz0, wx1, wy1, wz1); line = Line3D.cropLineToAxisAlignedBoundingBox(line, 0, dimensions.getWidth(), 0, dimensions.getHeight(), 0, dimensions.getDepth()); if (line != null) { Color color = getColorSource().getColor(series, item); LineObject3D line3D = new LineObject3D( (float) (line.getStart().getX() + xOffset), (float) (line.getStart().getY() + yOffset), (float) (line.getStart().getZ() + zOffset), (float) (line.getEnd().getX() + xOffset), (float) (line.getEnd().getY() + yOffset), (float) (line.getEnd().getZ() + zOffset), color); world.add(line3D); } } /** * Tests this renderer for equality with an arbitrary object. * * @param obj the object ({@code null} permitted). * * @return A boolean. */ @Override public boolean equals(Object obj) { if (obj == this) { return true; } if (!(obj instanceof LineXYZRenderer)) { return false; } LineXYZRenderer that = (LineXYZRenderer) obj; return super.equals(obj); } } orson-charts-2.1.0/src/main/java/org/jfree/chart3d/renderer/xyz/ScatterXYZRenderer.java000066400000000000000000000206311417331271500310220ustar00rootroot00000000000000/* =========================================================== * Orson Charts : a 3D chart library for the Java(tm) platform * =========================================================== * * (C)opyright 2013-2022, by David Gilbert. All rights reserved. * * https://github.com/jfree/orson-charts * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . * * [Oracle and Java are registered trademarks of Oracle and/or its affiliates. * Other names may be trademarks of their respective owners.] * * If you do not wish to be bound by the terms of the GPL, an alternative * commercial license can be purchased. For details, please see visit the * Orson Charts home page: * * http://www.object-refinery.com/orsoncharts/index.html * */ package org.jfree.chart3d.renderer.xyz; import java.awt.Color; import java.io.Serializable; import org.jfree.chart3d.Chart3DFactory; import org.jfree.chart3d.axis.Axis3D; import org.jfree.chart3d.data.xyz.XYZDataset; import org.jfree.chart3d.data.xyz.XYZItemKey; import org.jfree.chart3d.graphics3d.Dimension3D; import org.jfree.chart3d.graphics3d.Object3D; import org.jfree.chart3d.graphics3d.Offset3D; import org.jfree.chart3d.graphics3d.World; import org.jfree.chart3d.internal.Args; import org.jfree.chart3d.plot.XYZPlot; import org.jfree.chart3d.renderer.Renderer3DChangeEvent; /** * A renderer for 3D scatter plots. This renderer is used with an * {@link XYZPlot} and any {@link XYZDataset} instance. Here is a sample: *
* ScatterPlot3DDemo2.svg *
* (refer to {@code ScatterPlot3DDemo2.java} for the code to generate * the above chart). *

* TIP: to create a chart using this renderer, you can use the * {@link Chart3DFactory#createScatterChart(String, String, XYZDataset, String, String, String)} * method. *

* NOTE: This class is serializable, but the serialization format is subject * to change in future releases and should not be relied upon for persisting * instances of this class. */ @SuppressWarnings("serial") public class ScatterXYZRenderer extends AbstractXYZRenderer implements XYZRenderer, Serializable { /** The size of the cubes to render for each data point (in world units). */ private double size; /** The offsets for item labels, as a percentage of the size. */ private Offset3D itemLabelOffsetPercent; /** * Creates a new instance with default attribute values. */ public ScatterXYZRenderer() { super(); this.size = 0.10; this.itemLabelOffsetPercent = new Offset3D(0.0, 1.0, 0.0); } /** * Returns the size of the cubes (in world units) used to display each data * item. The default value is {@code 0.10}. * * @return The size (in world units). */ public double getSize() { return this.size; } /** * Sets the size (in world units) of the cubes used to represent each data * item and sends a {@link Renderer3DChangeEvent} to all registered * listeners. * * @param size the size (in world units, must be positive). */ public void setSize(double size) { Args.positiveRequired(size, "size"); this.size = size; fireChangeEvent(true); } /** * Returns the item label offsets. * * @return The item label offsets (never {@code null}). * * @since 1.3 */ public Offset3D getItemLabelOffsetPercent() { return this.itemLabelOffsetPercent; } /** * Sets the item label offsets and sends a change event to all registered * listeners. * * @param offset the new offset ({@code null} not permitted). * * @since 1.3 */ public void setItemLabelOffsetPercent(Offset3D offset) { Args.nullNotPermitted(offset, "offset"); this.itemLabelOffsetPercent = offset; fireChangeEvent(true); } /** * Constructs and places one item from the specified dataset into the given * world. The {@link XYZPlot} class will iterate over its dataset and * and call this method for each item (in other words, you don't need to * call this method directly). * * @param dataset the dataset ({@code null} not permitted). * @param series the series index. * @param item the item index. * @param world the world ({@code null} not permitted). * @param dimensions the dimensions ({@code null} not permitted). * @param xOffset the x-offset. * @param yOffset the y-offset. * @param zOffset the z-offset. */ @Override @SuppressWarnings("unchecked") public void composeItem(XYZDataset dataset, int series, int item, World world, Dimension3D dimensions, double xOffset, double yOffset, double zOffset) { double x = dataset.getX(series, item); double y = dataset.getY(series, item); double z = dataset.getZ(series, item); XYZPlot plot = getPlot(); Axis3D xAxis = plot.getXAxis(); Axis3D yAxis = plot.getYAxis(); Axis3D zAxis = plot.getZAxis(); double delta = this.size / 2.0; Dimension3D dim = plot.getDimensions(); double xx = xAxis.translateToWorld(x, dim.getWidth()); double xmin = Math.max(0.0, xx - delta); double xmax = Math.min(dim.getWidth(), xx + delta); double yy = yAxis.translateToWorld(y, dim.getHeight()); double ymin = Math.max(0.0, yy - delta); double ymax = Math.min(dim.getHeight(), yy + delta); double zz = zAxis.translateToWorld(z, dim.getDepth()); double zmin = Math.max(0.0, zz - delta); double zmax = Math.min(dim.getDepth(), zz + delta); if ((xmin >= xmax) || (ymin >= ymax) || (zmin >= zmax)) { return; } Color color = getColorSource().getColor(series, item); double cx = (xmax + xmin) / 2.0 + xOffset; double cy = (ymax + ymin) / 2.0 + yOffset; double cz = (zmax + zmin) / 2.0 + zOffset; Object3D cube = Object3D.createBox(cx, xmax - xmin, cy, ymax - ymin, cz, zmax - zmin, color); Comparable seriesKey = dataset.getSeriesKey(series); XYZItemKey itemKey = new XYZItemKey(seriesKey, item); cube.setProperty(Object3D.ITEM_KEY, itemKey); world.add(cube); if (getItemLabelGenerator() != null) { String label = getItemLabelGenerator().generateItemLabel(dataset, seriesKey, item); if (label != null) { double dx = this.itemLabelOffsetPercent.getDX() * this.size; double dy = this.itemLabelOffsetPercent.getDY() * this.size; double dz = this.itemLabelOffsetPercent.getDZ() * this.size; Object3D labelObj = Object3D.createLabelObject(label, getItemLabelFont(), getItemLabelColor(), getItemLabelBackgroundColor(), cx + dx, cy + dy, cz + dz, false, true); labelObj.setProperty(Object3D.ITEM_KEY, itemKey); world.add(labelObj); } } } /** * Tests this renderer for equality with an arbitrary object. * * @param obj the object to test ({@code null} permitted). * * @return A boolean. */ @Override public boolean equals(Object obj) { if (obj == this) { return true; } if (!(obj instanceof ScatterXYZRenderer)) { return false; } ScatterXYZRenderer that = (ScatterXYZRenderer) obj; if (this.size != that.size) { return false; } if (!this.itemLabelOffsetPercent.equals(that.itemLabelOffsetPercent)) { return false; } return super.equals(obj); } } orson-charts-2.1.0/src/main/java/org/jfree/chart3d/renderer/xyz/StandardXYZColorSource.java000066400000000000000000000121551417331271500316500ustar00rootroot00000000000000/* =========================================================== * Orson Charts : a 3D chart library for the Java(tm) platform * =========================================================== * * (C)opyright 2013-2022, by David Gilbert. All rights reserved. * * https://github.com/jfree/orson-charts * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . * * [Oracle and Java are registered trademarks of Oracle and/or its affiliates. * Other names may be trademarks of their respective owners.] * * If you do not wish to be bound by the terms of the GPL, an alternative * commercial license can be purchased. For details, please see visit the * Orson Charts home page: * * http://www.object-refinery.com/orsoncharts/index.html * */ package org.jfree.chart3d.renderer.xyz; import java.awt.Color; import java.io.Serializable; import org.jfree.chart3d.Colors; import org.jfree.chart3d.internal.Args; import org.jfree.chart3d.internal.ObjectUtils; /** * A standard implementation of the {@link XYZColorSource} interface. *

* NOTE: This class is serializable, but the serialization format is subject * to change in future releases and should not be relied upon for persisting * instances of this class. */ @SuppressWarnings("serial") public class StandardXYZColorSource implements XYZColorSource, Serializable { /** The sequence of color objects to use for each series. */ private Color[] colors; /** * Creates a new instance with default colors. */ public StandardXYZColorSource() { this(Colors.getDefaultColors()); } /** * Creates a new instance with the supplied sequence of colors. The * supplied array must have at least one entry, and all entries must be * non-{@code null}. * * @param colors the colors ({@code null} not permitted). */ public StandardXYZColorSource(Color... colors) { Args.nullNotPermitted(colors, "colors"); if (colors.length == 0) { throw new IllegalArgumentException( "Zero length array not permitted."); } for (Color c: colors) { if (c == null) { throw new IllegalArgumentException( "Null array entries not permitted."); } } this.colors = colors; } /** * Returns the color to use for the specified item. * * @param series the series index. * @param item the item index. * * @return The color (never {@code null}). */ @Override public Color getColor(int series, int item) { return this.colors[series % this.colors.length]; } /** * Returns the color to use in the legend for the specified series. * * @param series the series index. * * @return The color (never {@code null}). */ @Override public Color getLegendColor(int series) { return this.colors[series % this.colors.length]; } /** * Restyles the source using the specified colors. Refer to the * implementing class to confirm the precise behaviour (typically all * existing color settings are cleared and the specified colors are * installed as the new defaults). * * @param colors the colors. * * @since 1.2 */ @Override public void style(Color... colors) { Args.nullNotPermitted(colors, "colors"); if (colors.length == 0) { throw new IllegalArgumentException( "Zero length array not permitted."); } for (Color c: colors) { if (c == null) { throw new IllegalArgumentException( "Null array entries not permitted."); } } this.colors = colors.clone(); } /** * Tests this paint source for equality with an arbitrary object. * * @param obj the object ({@code null} permitted). * * @return A boolean. */ @Override public boolean equals(Object obj) { if (obj == this) { return true; } if (!(obj instanceof StandardXYZColorSource)) { return false; } StandardXYZColorSource that = (StandardXYZColorSource) obj; if (this.colors.length != that.colors.length) { return false; } for (int i = 0; i < this.colors.length; i++) { if (!ObjectUtils.equalsPaint(this.colors[i], that.colors[i])) { return false; } } return true; } } orson-charts-2.1.0/src/main/java/org/jfree/chart3d/renderer/xyz/SurfaceRenderer.java000066400000000000000000000556111417331271500304000ustar00rootroot00000000000000/* =========================================================== * Orson Charts : a 3D chart library for the Java(tm) platform * =========================================================== * * (C)opyright 2013-2022, by David Gilbert. All rights reserved. * * https://github.com/jfree/orson-charts * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . * * [Oracle and Java are registered trademarks of Oracle and/or its affiliates. * Other names may be trademarks of their respective owners.] * * If you do not wish to be bound by the terms of the GPL, an alternative * commercial license can be purchased. For details, please see visit the * Orson Charts home page: * * http://www.object-refinery.com/orsoncharts/index.html * */ package org.jfree.chart3d.renderer.xyz; import java.awt.Color; import java.io.Serializable; import java.util.ArrayList; import java.util.List; import org.jfree.chart3d.axis.ValueAxis3D; import org.jfree.chart3d.data.Range; import org.jfree.chart3d.data.function.Function3D; import org.jfree.chart3d.data.function.Function3DUtils; import org.jfree.chart3d.data.xyz.XYZDataset; import org.jfree.chart3d.graphics3d.Dimension3D; import org.jfree.chart3d.graphics3d.Object3D; import org.jfree.chart3d.graphics3d.Point3D; import org.jfree.chart3d.graphics3d.World; import org.jfree.chart3d.internal.Args; import org.jfree.chart3d.plot.XYZPlot; import org.jfree.chart3d.renderer.ColorScale; import org.jfree.chart3d.renderer.ColorScaleRenderer; import org.jfree.chart3d.renderer.ComposeType; import org.jfree.chart3d.renderer.FixedColorScale; import org.jfree.chart3d.renderer.Renderer3DChangeEvent; /** * A renderer that plots a surface based on a function (any implementation * of {@link Function3D}). This renderer is different to others in that it * does not plot data from a dataset, instead it samples a function and plots * those values. By default 900 samples are taken (30 x-values by 30 z-values) * although this can be modified. *

* For the fastest rendering, the {@code drawFaceOutlines} flag can be set * to {@code false} (the default is {@code true}) but this may * cause slight rendering artifacts if anti-aliasing is on (note that switching * off anti-aliasing as well also improves rendering performance). *

* NOTE: This class is serializable, but the serialization format is subject * to change in future releases and should not be relied upon for persisting * instances of this class. * * @since 1.1 */ @SuppressWarnings("serial") public class SurfaceRenderer extends AbstractXYZRenderer implements XYZRenderer, ColorScaleRenderer, Serializable { /** The function. */ private Function3D function; /** The number of samples along the x-axis (minimum 2). */ private int xSamples; /** The number of samples along the z-axis (minimum 2). */ private int zSamples; /** The color scale. */ private ColorScale colorScale; /** * A flag that controls whether the faces that make up the surface have * their outlines drawn (in addition to the shape being filled). The * default value is {@code true} which renders a solid surface but * is slower. */ private boolean drawFaceOutlines; /** * Creates a new renderer for the specified function. By default, the * renderer will take 30 samples along the x-axis and 30 samples along the * z-axis (this is configurable). * * @param function the function ({@code null} not permitted). */ public SurfaceRenderer(Function3D function) { Args.nullNotPermitted(function, "function"); this.function = function; this.xSamples = 30; this.zSamples = 30; this.colorScale = new FixedColorScale(Color.YELLOW); this.drawFaceOutlines = true; } /** * Returns the number of samples the renderer will take along the * x-axis when plotting the function. The default value is 30. * * @return The number of samples. */ public int getXSamples() { return this.xSamples; } /** * Sets the number of samples the renderer will take along the x-axis when * plotting the function and sends a {@link Renderer3DChangeEvent} to all * registered listeners. The default value is 30, setting this to higher * values will result in smoother looking plots, but they will take * longer to draw. * * @param count the count. * * @see #setZSamples(int) */ public void setXSamples(int count) { this.xSamples = count; fireChangeEvent(true); } /** * Returns the number of samples the renderer will take along the z-axis * when plotting the function and sends a {@link Renderer3DChangeEvent} to * all registered listeners. The default value is 30. * * @return The number of samples. */ public int getZSamples() { return this.zSamples; } /** * Sets the number of samples the renderer will take along the z-axis when * plotting the function and sends a {@link Renderer3DChangeEvent} to all * registered listeners. The default value is 30, setting this to higher * values will result in smoother looking plots, but they will take * longer to draw. * * @param count the count. * * @see #setXSamples(int) */ public void setZSamples(int count) { this.zSamples = count; } /** * Returns the compose-type for the renderer. Here the value is * {@code ComposeType.ALL} which means the plot will call the * {@link #composeAll(org.jfree.chart3d.plot.XYZPlot, * org.jfree.chart3d.graphics3d.World, org.jfree.chart3d.graphics3d.Dimension3D, * double, double, double)} method for composing the chart. * * @return The compose type (never {@code null}). */ @Override public ComposeType getComposeType() { return ComposeType.ALL; } /** * Returns the color scale. This determines the color of the surface * according to the y-value. * * @return The color scale (never {@code null}). */ @Override public ColorScale getColorScale() { return this.colorScale; } /** * Sets the color scale and sends a {@link Renderer3DChangeEvent} to all * registered listeners. * * @param colorScale the color scale ({@code null} not permitted). */ public void setColorScale(ColorScale colorScale) { Args.nullNotPermitted(colorScale, "colorScale"); this.colorScale = colorScale; fireChangeEvent(true); } /** * Returns the flag that controls whether or not the faces that make * up the surface have their outlines drawn during rendering. The * default value is {@code true}. * * @return A boolean. */ public boolean getDrawFaceOutlines() { return this.drawFaceOutlines; } /** * Sets a flag that controls whether or not the faces that make up the * surface are drawn (as well as filled) and sends a * {@link Renderer3DChangeEvent} to all registered listeners. If the face * outlines are drawn (the default), the surface is solid (but takes longer * to draw). If the face outlines are not drawn, Java2D can leave small * gaps that you can "see" through (if you don't mind this, then the * performance is better). * * @param draw the new flag value. */ public void setDrawFaceOutlines(boolean draw) { this.drawFaceOutlines = draw; fireChangeEvent(true); } /** * Composes the entire representation of the function in the supplied * {@code world}. * * @param plot the plot. * @param world the world. * @param dimensions the plot dimensions. * @param xOffset the x-offset. * @param yOffset the y-offset. * @param zOffset the z-offset. */ @Override public void composeAll(XYZPlot plot, World world, Dimension3D dimensions, double xOffset, double yOffset, double zOffset) { // need to know the x-axis range and the z-axis range ValueAxis3D xAxis = plot.getXAxis(); ValueAxis3D yAxis = plot.getYAxis(); ValueAxis3D zAxis = plot.getZAxis(); Dimension3D dim = plot.getDimensions(); double xlen = dim.getWidth(); double ylen = dim.getHeight(); double zlen = dim.getDepth(); Range yRange = new Range(yOffset, -yOffset); for (int xIndex = 0; xIndex < this.xSamples; xIndex++) { double xfrac0 = xIndex / (double) this.xSamples; double xfrac1 = (xIndex + 1) / (double) this.xSamples; for (int zIndex = 0; zIndex < this.zSamples; zIndex++) { double zfrac0 = zIndex / (double) this.zSamples; double zfrac1 = (zIndex + 1) / (double) this.zSamples; double x0 = xAxis.getRange().value(xfrac0); double x1 = xAxis.getRange().value(xfrac1); double xm = x0 / 2.0 + x1 / 2.0; double z0 = zAxis.getRange().value(zfrac0); double z1 = zAxis.getRange().value(zfrac1); double zm = z0 / 2.0 + z1 / 2.0; double y00 = this.function.getValue(x0, z0); double y01 = this.function.getValue(x0, z1); double y10 = this.function.getValue(x1, z0); double y11 = this.function.getValue(x1, z1); double ymm = this.function.getValue(xm, zm); double wx0 = xAxis.translateToWorld(x0, xlen) + xOffset; double wx1 = xAxis.translateToWorld(x1, xlen) + xOffset; double wy00 = yAxis.translateToWorld(y00, ylen) + yOffset; double wy01 = yAxis.translateToWorld(y01, ylen) + yOffset; double wy10 = yAxis.translateToWorld(y10, ylen) + yOffset; double wy11 = yAxis.translateToWorld(y11, ylen) + yOffset; double wz0 = zAxis.translateToWorld(z0, zlen) + zOffset; double wz1 = zAxis.translateToWorld(z1, zlen) + zOffset; Color color = this.colorScale.valueToColor(ymm); Object3D obj = new Object3D(color, this.drawFaceOutlines); List pts1 = facePoints1(wx0, wx1, wz0, wz1, wy00, wy01, wy11, yRange); int count1 = pts1.size(); for (Point3D pt : pts1) { obj.addVertex(pt); } if (count1 == 3) { obj.addDoubleSidedFace(new int[] {0, 1, 2}); } else if (count1 == 4) { obj.addDoubleSidedFace(new int[] {0, 1, 2, 3}); } else if (count1 == 5) { obj.addDoubleSidedFace(new int[] {0, 1, 2, 3, 4}); } List pts2 = facePoints2(wx0, wx1, wz0, wz1, wy00, wy11, wy10, yRange); int count2 = pts2.size(); for (Point3D pt : pts2) { obj.addVertex(pt); } if (count2 == 3) { obj.addDoubleSidedFace(new int[] {count1, count1 + 1, count1 + 2}); } else if (count2 == 4) { obj.addDoubleSidedFace(new int[] {count1, count1 + 1, count1 + 2, count1 + 3}); } else if (count2 == 5) { obj.addDoubleSidedFace(new int[] {count1, count1 + 1, count1 + 2, count1 + 3, count1 + 4}); } world.add(obj); } } } private Point3D intersectPoint(double x0, double y0, double z0, double x1, double y1, double z1, double yy) { double p = (yy - y0) / (y1 - y0); double x = x0 + p * (x1 - x0); double y = y0 + p * (y1 - y0); double z = z0 + p * (z1 - z0); return new Point3D(x, y, z); } private List facePoints1(double x0, double x1, double z0, double z1, double y00, double y01, double y11, Range yRange) { List pts = new ArrayList<>(4); double ymin = yRange.getMin(); double ymax = yRange.getMax(); // handle y00 if (y00 > yRange.getMax()) { if (yRange.contains(y01)) { pts.add(intersectPoint(x0, y00, z0, x0, y01, z1, ymax)); } else if (y01 < yRange.getMin()) { pts.add(intersectPoint(x0, y00, z0, x0, y01, z1, ymax)); pts.add(intersectPoint(x0, y00, z0, x0, y01, z1, ymin)); } } else if (yRange.contains(y00)) { pts.add(new Point3D(x0, y00, z0)); if (y01 > yRange.getMax()) { pts.add(intersectPoint(x0, y00, z0, x0, y01, z1, ymax)); } else if (y01 < yRange.getMin()) { pts.add(intersectPoint(x0, y00, z0, x0, y01, z1, ymin)); } } else { // below the range if (yRange.contains(y01)) { pts.add(intersectPoint(x0, y00, z0, x0, y01, z1, ymin)); } else if (y01 > yRange.getMax()) { pts.add(intersectPoint(x0, y00, z0, x0, y01, z1, ymin)); pts.add(intersectPoint(x0, y00, z0, x0, y01, z1, ymax)); } } // handle y01 if (y01 > yRange.getMax()) { if (yRange.contains(y11)) { pts.add(intersectPoint(x0, y01, z1, x1, y11, z1, ymax)); } else if (y11 < yRange.getMin()) { pts.add(intersectPoint(x0, y01, z1, x1, y11, z1, ymax)); pts.add(intersectPoint(x0, y01, z1, x1, y11, z1, ymin)); } } else if (yRange.contains(y01)) { pts.add(new Point3D(x0, y01, z1)); if (y11 > yRange.getMax()) { pts.add(intersectPoint(x0, y01, z1, x1, y11, z1, ymax)); } else if (y11 < yRange.getMin()) { pts.add(intersectPoint(x0, y01, z1, x1, y11, z1, ymin)); } } else { if (y11 > yRange.getMax()) { pts.add(intersectPoint(x0, y01, z1, x1, y11, z1, ymin)); pts.add(intersectPoint(x0, y01, z1, x1, y11, z1, ymax)); } else if (yRange.contains(y11)) { pts.add(intersectPoint(x0, y01, z1, x1, y11, z1, ymin)); } } // handle y11 if (y11 > yRange.getMax()) { if (yRange.contains(y00)) { pts.add(intersectPoint(x1, y11, z1, x0, y00, z0, ymax)); } else if (y00 < yRange.getMin()) { pts.add(intersectPoint(x1, y11, z1, x0, y00, z0, ymax)); pts.add(intersectPoint(x1, y11, z1, x0, y00, z0, ymin)); } } else if (yRange.contains(y11)) { pts.add(new Point3D(x1, y11, z1)); if (y00 > yRange.getMax()) { pts.add(intersectPoint(x1, y11, z1, x0, y00, z0, ymax)); } else if (y00 < yRange.getMin()) { pts.add(intersectPoint(x1, y11, z1, x0, y00, z0, ymin)); } } else { if (y00 > yRange.getMax()) { pts.add(intersectPoint(x1, y11, z1, x0, y00, z0, ymin)); pts.add(intersectPoint(x1, y11, z1, x0, y00, z0, ymax)); } else if (yRange.contains(y00)) { pts.add(intersectPoint(x1, y11, z1, x0, y00, z0, ymin)); } } return pts; } private List facePoints2(double x0, double x1, double z0, double z1, double y00, double y11, double y10, Range yRange) { List pts = new ArrayList<>(4); double ymin = yRange.getMin(); double ymax = yRange.getMax(); // handle y00 if (y00 > yRange.getMax()) { if (yRange.contains(y11)) { pts.add(intersectPoint(x0, y00, z0, x1, y11, z1, ymax)); } else if (y11 < yRange.getMin()) { pts.add(intersectPoint(x0, y00, z0, x1, y11, z1, ymax)); pts.add(intersectPoint(x0, y00, z0, x1, y11, z1, ymin)); } } else if (yRange.contains(y00)) { pts.add(new Point3D(x0, y00, z0)); if (y11 > yRange.getMax()) { pts.add(intersectPoint(x0, y00, z0, x1, y11, z1, ymax)); } else if (y11 < yRange.getMin()) { pts.add(intersectPoint(x0, y00, z0, x1, y11, z1, ymin)); } } else { // below the range if (yRange.contains(y11)) { pts.add(intersectPoint(x0, y00, z0, x1, y11, z1, ymin)); } else if (y11 > yRange.getMax()) { pts.add(intersectPoint(x0, y00, z0, x1, y11, z1, ymin)); pts.add(intersectPoint(x0, y00, z0, x1, y11, z1, ymax)); } } // handle y11 if (y11 > yRange.getMax()) { if (yRange.contains(y10)) { pts.add(intersectPoint(x1, y11, z1, x1, y10, z0, ymax)); } else if (y10 < yRange.getMin()) { pts.add(intersectPoint(x1, y11, z1, x1, y10, z0, ymax)); pts.add(intersectPoint(x1, y11, z1, x1, y10, z0, ymin)); } } else if (yRange.contains(y11)) { pts.add(new Point3D(x1, y11, z1)); if (y10 > yRange.getMax()) { pts.add(intersectPoint(x1, y11, z1, x1, y10, z0, ymax)); } else if (y10 < yRange.getMin()) { pts.add(intersectPoint(x1, y11, z1, x1, y10, z0, ymin)); } } else { if (y10 > yRange.getMax()) { pts.add(intersectPoint(x1, y11, z1, x1, y10, z0, ymin)); pts.add(intersectPoint(x1, y11, z1, x1, y10, z0, ymax)); } else if (yRange.contains(y10)) { pts.add(intersectPoint(x1, y11, z1, x1, y10, z0, ymin)); } } // handle y10 if (y10 > yRange.getMax()) { if (yRange.contains(y00)) { pts.add(intersectPoint(x1, y10, z0, x0, y00, z0, ymax)); } else if (y00 < yRange.getMin()) { pts.add(intersectPoint(x1, y10, z0, x0, y00, z0, ymax)); pts.add(intersectPoint(x1, y10, z0, x0, y00, z0, ymin)); } } else if (yRange.contains(y10)) { pts.add(new Point3D(x1, y10, z0)); if (y00 > yRange.getMax()) { pts.add(intersectPoint(x1, y10, z0, x0, y00, z0, ymax)); } else if (y00 < yRange.getMin()) { pts.add(intersectPoint(x1, y10, z0, x0, y00, z0, ymin)); } } else { if (y00 > yRange.getMax()) { pts.add(intersectPoint(x1, y10, z0, x0, y00, z0, ymin)); pts.add(intersectPoint(x1, y10, z0, x0, y00, z0, ymax)); } else if (yRange.contains(y00)) { pts.add(intersectPoint(x1, y10, z0, x0, y00, z0, ymin)); } } return pts; } /** * Throws an {@code UnsupportedOperationException} because this * renderer does not support per-item rendering. * * @param dataset the dataset ({@code null} not permitted). * @param series the series index. * @param item the item index. * @param world the world ({@code null} not permitted). * @param dimensions the dimensions ({@code null} not permitted). * @param xOffset the x-offset. * @param yOffset the y-offset. * @param zOffset the z-offset. */ @Override public void composeItem(XYZDataset dataset, int series, int item, World world, Dimension3D dimensions, double xOffset, double yOffset, double zOffset) { throw new UnsupportedOperationException( "Not supported by this renderer."); } /** * Returns the current range for the x-axis - the method is overridden * because this renderer does not use a dataset (it samples and plots a * function directly). * * @param dataset the dataset (ignored). * * @return The x-range (never {@code null}). */ @Override public Range findXRange(XYZDataset dataset) { return getPlot().getXAxis().getRange(); } /** * Returns the range that the renderer requires on the y-axis to display * all the data in the function. * * @param dataset the dataset (ignored). * * @return The range. */ @Override public Range findYRange(XYZDataset dataset) { return Function3DUtils.findYRange(this.function, getPlot().getXAxis().getRange(), getPlot().getZAxis().getRange(), this.xSamples, this.zSamples, true); } /** * Returns the current range for the z-axis - the method is overridden * because this renderer does not use a dataset (it samples and plots a * function directly). * * @param dataset the dataset (ignored). * * @return The z-range (never {@code null}). */ @Override public Range findZRange(XYZDataset dataset) { return getPlot().getZAxis().getRange(); } /** * Tests this renderer for equality with an arbitrary object. * * @param obj the object ({@code null} not permitted). * * @return A boolean. */ @Override public boolean equals(Object obj) { if (obj == this) { return true; } if (!(obj instanceof SurfaceRenderer)) { return false; } SurfaceRenderer that = (SurfaceRenderer) obj; if (!this.function.equals(that.function)) { return false; } if (this.xSamples != that.xSamples) { return false; } if (this.zSamples != that.zSamples) { return false; } if (!this.colorScale.equals(that.colorScale)) { return false; } if (this.drawFaceOutlines != that.drawFaceOutlines) { return false; } return super.equals(obj); } } orson-charts-2.1.0/src/main/java/org/jfree/chart3d/renderer/xyz/XYZColorSource.java000066400000000000000000000050401417331271500301620ustar00rootroot00000000000000/* =========================================================== * Orson Charts : a 3D chart library for the Java(tm) platform * =========================================================== * * (C)opyright 2013-2022, by David Gilbert. All rights reserved. * * https://github.com/jfree/orson-charts * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . * * [Oracle and Java are registered trademarks of Oracle and/or its affiliates. * Other names may be trademarks of their respective owners.] * * If you do not wish to be bound by the terms of the GPL, an alternative * commercial license can be purchased. For details, please see visit the * Orson Charts home page: * * http://www.object-refinery.com/orsoncharts/index.html * */ package org.jfree.chart3d.renderer.xyz; import java.awt.Color; /** * A source of {@code Color} values for an {@link XYZRenderer}. *

* Classes that implement this interface should also implement * {@code java.io.Serializable}, otherwise it will not be possible to * serialize and deserialize charts that use the non-serializable instance. */ public interface XYZColorSource { /** * Returns the color for one item in the plot. * * @param series the series index. * @param item the item index. * * @return The color (never {@code null}). */ Color getColor(int series, int item); /** * Returns the color that represents the specified series. * * @param series the series index. * * @return The color (never {@code null}). */ Color getLegendColor(int series); /** * Restyles the source using the specified colors. Refer to the * implementing class to confirm the precise behaviour (typically all * existing color settings are cleared and the specified colors are * installed as the new defaults). * * @param colors the colors. * * @since 1.2 */ void style(Color... colors); } orson-charts-2.1.0/src/main/java/org/jfree/chart3d/renderer/xyz/XYZRenderer.java000066400000000000000000000141471417331271500275010ustar00rootroot00000000000000/* =========================================================== * Orson Charts : a 3D chart library for the Java(tm) platform * =========================================================== * * (C)opyright 2013-2022, by David Gilbert. All rights reserved. * * https://github.com/jfree/orson-charts * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . * * [Oracle and Java are registered trademarks of Oracle and/or its affiliates. * Other names may be trademarks of their respective owners.] * * If you do not wish to be bound by the terms of the GPL, an alternative * commercial license can be purchased. For details, please see visit the * Orson Charts home page: * * http://www.object-refinery.com/orsoncharts/index.html * */ package org.jfree.chart3d.renderer.xyz; import java.awt.Color; import org.jfree.chart3d.data.Range; import org.jfree.chart3d.data.xyz.XYZDataset; import org.jfree.chart3d.graphics3d.Dimension3D; import org.jfree.chart3d.graphics3d.World; import org.jfree.chart3d.plot.XYZPlot; import org.jfree.chart3d.renderer.ComposeType; import org.jfree.chart3d.renderer.Renderer3D; import org.jfree.chart3d.renderer.Renderer3DChangeEvent; /** * A renderer that can display data from an {@link XYZDataset} on an * {@link XYZPlot}. */ public interface XYZRenderer extends Renderer3D { /** * Returns the plot that this renderer is assigned to. * * @return The plot (possibly {@code null}). */ XYZPlot getPlot(); /** * Sets the plot that the renderer is assigned to. Although this method * is part of the public API, client code should not need to call it. * * @param plot the plot ({@code null} permitted). */ void setPlot(XYZPlot plot); /** * Returns the color source for the renderer, which is an object that * is responsible for providing the colors used by the renderer to draw * data (and legend) items. * * @return The paint source (never {@code null}). */ XYZColorSource getColorSource(); /** * Sets the color source for the renderer and sends a * {@link Renderer3DChangeEvent} to all registered listeners. * * @param source the color source ({@code null} not permitted). * * @since 1.2 */ void setColorSource(XYZColorSource source); /** * Sets the colors for the renderer. * * @param colors the colors. * * @since 1.2 */ void setColors(Color... colors); /** * Returns the range that should be set on the x-axis in order for this * renderer to be able to display all the data in the supplied dataset. * If the dataset contains no data, this method returns {@code null}. * * @param dataset the dataset ({@code null} not permitted). * * @return The range (possibly {@code null}). */ Range findXRange(XYZDataset dataset); /** * Returns the range that should be set on the y-axis in order for this * renderer to be able to display all the data in the supplied dataset. * If the dataset contains no data, this method returns {@code null}. * * @param dataset the dataset ({@code null} not permitted). * * @return The range. */ Range findYRange(XYZDataset dataset); /** * Returns the range that should be set on the z-axis in order for this * renderer to be able to display all the data in the supplied dataset. * If the dataset contains no data, this method returns {@code null}. * * @param dataset the dataset ({@code null} not permitted). * * @return The range. */ Range findZRange(XYZDataset dataset); /** * Returns the type of composition performed by the renderer. This * determines whether the plot will call the {@code composeItem()} * method (once for each data item) or just call the * {@code composeAll()} method once. * * @return The type of composition (never {@code null}). * * @since 1.1 */ ComposeType getComposeType(); /** * Constructs and places one item from the specified dataset into the given * world. The {@link XYZPlot} class will iterate over its dataset and * and call this method for each item (in other words, you don't need to * call this method directly). * * @param dataset the dataset ({@code null} not permitted). * @param series the series index. * @param item the item index. * @param world the world ({@code null} not permitted). * @param dimensions the dimensions ({@code null} not permitted). * @param xOffset the x-offset. * @param yOffset the y-offset. * @param zOffset the z-offset. */ void composeItem(XYZDataset dataset, int series, int item, World world, Dimension3D dimensions, double xOffset, double yOffset, double zOffset); /** * Composes all the 3D objects that this renderer needs to present. This * method only needs to be implemented if the {@code getComposeType()} * method returns {@code ALL}, otherwise it can be left empty. * * @param plot the plot. * @param world the world ({@code null} not permitted). * @param dimensions the dimensions ({@code null} not permitted). * @param xOffset the x-offset. * @param yOffset the y-offset. * @param zOffset the z-offset. * * @since 1.1 */ void composeAll(XYZPlot plot, World world, Dimension3D dimensions, double xOffset, double yOffset, double zOffset); } orson-charts-2.1.0/src/main/java/org/jfree/chart3d/renderer/xyz/package-info.java000066400000000000000000000002111417331271500276270ustar00rootroot00000000000000/** * Renderers that can be used with the * {@link org.jfree.chart3d.plot.XYZPlot} class. */ package org.jfree.chart3d.renderer.xyz; orson-charts-2.1.0/src/main/java/org/jfree/chart3d/style/000077500000000000000000000000001417331271500231465ustar00rootroot00000000000000orson-charts-2.1.0/src/main/java/org/jfree/chart3d/style/ChartStyle.java000066400000000000000000000225071417331271500261010ustar00rootroot00000000000000/* =========================================================== * Orson Charts : a 3D chart library for the Java(tm) platform * =========================================================== * * (C)opyright 2013-2022, by David Gilbert. All rights reserved. * * https://github.com/jfree/orson-charts * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . * * [Oracle and Java are registered trademarks of Oracle and/or its affiliates. * Other names may be trademarks of their respective owners.] * * If you do not wish to be bound by the terms of the GPL, an alternative * commercial license can be purchased. For details, please see visit the * Orson Charts home page: * * http://www.object-refinery.com/orsoncharts/index.html * */ package org.jfree.chart3d.style; import java.awt.Color; import java.awt.Font; import java.awt.Shape; import java.awt.Stroke; import org.jfree.chart3d.Chart3D; import org.jfree.chart3d.table.RectanglePainter; /** * A chart style provides styling attributes for a chart. To apply a style * to a chart, use the * {@link Chart3D#setStyle(org.jfree.chart3d.style.ChartStyle)} method. See the * {@link ChartStyles} class for predefined styles. * * @since 1.2 */ public interface ChartStyle { /** * Returns the painter that fills the background for the chart. * * @return The painter (never {@code null}). */ RectanglePainter getBackgroundPainter(); /** * Returns the title font. * * @return The title font (never {@code null}). */ Font getTitleFont(); /** * Returns the foreground color for the chart title. * * @return The foreground color (never {@code null}). */ Color getTitleColor(); /** * Returns the background color for the chart title. * * @return The background color for the chart title (never * {@code null}). */ Color getTitleBackgroundColor(); /** * Returns the subtitle font. * * @return The subtitle font (never {@code null}). */ Font getSubtitleFont(); /** * Returns the foreground color for the chart subtitle. * * @return The foreground color (never {@code null}). */ Color getSubtitleColor(); /** * Returns the background color for the chart subtitle. * * @return The background color (never {@code null}). */ Color getSubtitleBackgroundColor(); /** * Returns the color for the chart box, if any. * * @return The color for the chart box (never {@code null}). */ Color getChartBoxColor(); /** * Returns the flag that controls whether or not gridlines are drawn * perpendicular to the column axis in category plots. * * @return A boolean. */ boolean getColumnAxisGridlinesVisible(); /** * Returns the flag that controls whether or not gridlines are drawn * perpendicular to the row axis in category plots. * * @return A boolean. */ boolean getRowAxisGridlinesVisible(); /** * Returns the flag that controls whether or not gridlines are drawn * perpendicular to the x-axis (or column axis). * * @return A boolean. */ boolean getXAxisGridlinesVisible(); /** * Returns the flag that controls whether or not gridlines are drawn * perpendicular to the y-axis (or value axis). * * @return A boolean. */ boolean getYAxisGridlinesVisible(); /** * Returns the flag that controls whether or not gridlines are drawn * perpendicular to the z-axis (or row axis). * * @return A boolean. */ boolean getZAxisGridlinesVisible(); /** * Returns the color used to draw the gridlines. * * @return The color (never {@code null}). */ Color getGridlineColor(); /** * Returns the stroke used to draw the gridlines. * * @return The stroke (never {@code null}). */ Stroke getGridlineStroke(); /** * Returns the font used for pie section labels. * * @return The pie section label font (never {@code null}). */ Font getSectionLabelFont(); /** * Returns the foreground color used for pie section labels. * * @return The pie section label color (never {@code null}). */ Color getSectionLabelColor(); /** * Returns the standard colors for the style. * * @return The standard colors (never {@code null}). */ Color[] getStandardColors(); /** * Returns the axis label font. The axis label is usually a description * of what the axis represents. * * @return The axis label font (never {@code null}). * * @see #getAxisTickLabelFont() */ Font getAxisLabelFont(); /** * Returns the foreground color for axis labels. * * @return The foreground color (never {@code null}). */ Color getAxisLabelColor(); /** * Returns the axis tick label font. * * @return The axis tick label font (never {@code null}). * * @see #getAxisLabelFont() */ Font getAxisTickLabelFont(); /** * Returns the color used to draw the tick labels on the axis. * * @return The color (never {@code null}). */ Color getAxisTickLabelColor(); /** * Returns the legend header font. * * @return The legend header font (never {@code null}). */ Font getLegendHeaderFont(); /** * Returns the foreground color for the legend header if there is one. * * @return The color (never {@code null}). */ Color getLegendHeaderColor(); /** * Returns the background color for the legend header if there is one. * * @return The color (never {@code null}). */ Color getLegendHeaderBackgroundColor(); /** * Returns the standard shape for legend items. * * @return The legend shape (never {@code null}). */ Shape getLegendItemShape(); /** * Returns the legend item font. * * @return The legend item font (never {@code null}). */ Font getLegendItemFont(); /** * Returns the foreground color for legend items. * * @return The foreground color (never {@code null}). */ Color getLegendItemColor(); /** * Returns the background color for legend items. * * @return The background color (never {@code null}). */ Color getLegendItemBackgroundColor(); /** * Returns the legend footer font. * * @return The legend footer font (never {@code null}). */ Font getLegendFooterFont(); /** * Returns the color used for the legend footer text (if any). * * @return The color (never {@code null}). */ Color getLegendFooterColor(); /** * Returns the color used for the background of legend footer text (if any). * * @return The color (never {@code null}). */ Color getLegendFooterBackgroundColor(); /** * Returns the font used to draw marker labels. * * @return The font used to draw marker labels (never {@code null}). */ Font getMarkerLabelFont(); /** * Returns the color for the marker labels. * * @return The color for the marker labels (never {@code null}). */ Color getMarkerLabelColor(); /** * Returns the stroke used to draw marker lines. * * @return The stroke used to draw marker lines (never {@code null}). */ Stroke getMarkerLineStroke(); /** * Returns the color used to draw marker lines. * * @return The color used to draw marker lines (never {@code null}). */ Color getMarkerLineColor(); /** * Returns the color used to fill the band representing the marker range. * * @return The fill color (never {@code null}). */ Color getMarkerFillColor(); /** * Returns a clone of the chart style. * * @return A clone (never {@code null}). */ ChartStyle clone(); /** * Registers a listener to receive notification of changes to the chart * style. Typically the chart registers with its style, and applies the * style changes when it receives notification of any change. * * @param listener the listener ({@code null} not permitted). */ void addChangeListener(ChartStyleChangeListener listener); /** * Deregisters a listener so that it no longer receives notification of * chart changes. * * @param listener the listener ({@code null} not permitted). */ void removeChangeListener(ChartStyleChangeListener listener); } orson-charts-2.1.0/src/main/java/org/jfree/chart3d/style/ChartStyleChangeEvent.java000066400000000000000000000050541417331271500302070ustar00rootroot00000000000000/* =========================================================== * Orson Charts : a 3D chart library for the Java(tm) platform * =========================================================== * * (C)opyright 2013-2022, by David Gilbert. All rights reserved. * * https://github.com/jfree/orson-charts * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . * * [Oracle and Java are registered trademarks of Oracle and/or its affiliates. * Other names may be trademarks of their respective owners.] * * If you do not wish to be bound by the terms of the GPL, an alternative * commercial license can be purchased. For details, please see visit the * Orson Charts home page: * * http://www.object-refinery.com/orsoncharts/index.html * */ package org.jfree.chart3d.style; import java.util.EventObject; import org.jfree.chart3d.internal.Args; /** * An event that signals a change to a {@link ChartStyle}. *

* NOTE: This class is serializable, but the serialization format is subject * to change in future releases and should not be relied upon for persisting * instances of this class. * * @since 1.2 */ @SuppressWarnings("serial") public class ChartStyleChangeEvent extends EventObject { private ChartStyle style; /** * Creates a new event. * * @param style the style ({@code null} not permitted). */ public ChartStyleChangeEvent(ChartStyle style) { this(style, style); } /** * Creates a new event. * * @param source the source. * @param style the style ({@code null} not permitted). */ public ChartStyleChangeEvent(Object source, ChartStyle style) { super(source); Args.nullNotPermitted(style, "style"); this.style = style; } /** * Returns the chart style that this event is associated with. * * @return The style (never {@code null}). */ public ChartStyle getChartStyle () { return this.style; } } orson-charts-2.1.0/src/main/java/org/jfree/chart3d/style/ChartStyleChangeListener.java000066400000000000000000000036361417331271500307170ustar00rootroot00000000000000/* =========================================================== * Orson Charts : a 3D chart library for the Java(tm) platform * =========================================================== * * (C)opyright 2013-2022, by David Gilbert. All rights reserved. * * https://github.com/jfree/orson-charts * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . * * [Oracle and Java are registered trademarks of Oracle and/or its affiliates. * Other names may be trademarks of their respective owners.] * * If you do not wish to be bound by the terms of the GPL, an alternative * commercial license can be purchased. For details, please see visit the * Orson Charts home page: * * http://www.object-refinery.com/orsoncharts/index.html * */ package org.jfree.chart3d.style; import java.util.EventListener; import org.jfree.chart3d.Chart3D; /** * An interface for receiving notification of changes to a {@link ChartStyle} * instance. *

* The {@link Chart3D} class implements this interface so that it can * receive notification of changes to the chart style. * * @since 1.2 */ public interface ChartStyleChangeListener extends EventListener { /** * Called to inform that a chart change event has occurred. * * @param event the event. */ void styleChanged(ChartStyleChangeEvent event); } orson-charts-2.1.0/src/main/java/org/jfree/chart3d/style/ChartStyler.java000066400000000000000000000264471417331271500262720ustar00rootroot00000000000000/* =========================================================== * Orson Charts : a 3D chart library for the Java(tm) platform * =========================================================== * * (C)opyright 2013-2022, by David Gilbert. All rights reserved. * * https://github.com/jfree/orson-charts * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . * * [Oracle and Java are registered trademarks of Oracle and/or its affiliates. * Other names may be trademarks of their respective owners.] * * If you do not wish to be bound by the terms of the GPL, an alternative * commercial license can be purchased. For details, please see visit the * Orson Charts home page: * * http://www.object-refinery.com/orsoncharts/index.html * */ package org.jfree.chart3d.style; import java.awt.Color; import java.awt.Font; import java.util.HashMap; import java.util.Map; import org.jfree.chart3d.Chart3D; import org.jfree.chart3d.ChartElement; import org.jfree.chart3d.ChartElementVisitor; import org.jfree.chart3d.axis.Axis3D; import org.jfree.chart3d.axis.CategoryAxis3D; import org.jfree.chart3d.axis.ValueAxis3D; import org.jfree.chart3d.marker.CategoryMarker; import org.jfree.chart3d.marker.Marker; import org.jfree.chart3d.marker.NumberMarker; import org.jfree.chart3d.marker.RangeMarker; import org.jfree.chart3d.plot.CategoryPlot3D; import org.jfree.chart3d.plot.PiePlot3D; import org.jfree.chart3d.plot.Plot3D; import org.jfree.chart3d.plot.XYZPlot; import org.jfree.chart3d.renderer.Renderer3D; import org.jfree.chart3d.renderer.category.CategoryRenderer3D; import org.jfree.chart3d.renderer.xyz.XYZRenderer; import org.jfree.chart3d.table.TableElement; import org.jfree.chart3d.table.TableElementStyler; /** * A {@link ChartElementVisitor} that applies a chart style to the elements * of a chart. * * @since 1.2 */ public class ChartStyler implements ChartElementVisitor { /** The chart style. */ private final ChartStyle style; /** * Creates a new instance. * * @param style the style ({@code null} not permitted). */ public ChartStyler(ChartStyle style) { this.style = style; } /** * Visits a chart element and applies the current style to that element. * * @param element the chart element (never {@code null}). */ @Override public void visit(ChartElement element) { if (element instanceof Chart3D) { Chart3D chart = (Chart3D) element; styleChart(chart); } if (element instanceof Plot3D) { Plot3D plot = (Plot3D) element; stylePlot(plot); } if (element instanceof Axis3D) { Axis3D axis = (Axis3D) element; styleAxis(axis); } if (element instanceof Renderer3D) { Renderer3D renderer = (Renderer3D) element; styleRenderer(renderer); } if (element instanceof Marker) { Marker marker = (Marker) element; styleMarker(marker); } } /** * Applies the current style to a chart. * * @param chart the chart ({@code null} not permitted). */ protected void styleChart(Chart3D chart) { chart.setBackground(this.style.getBackgroundPainter()); // if the chart title font changed, visit all table elements in the // chart title and change the font for any element that is tagged as // "CHART_TITLE" TableElement chartTitle = chart.getTitle(); if (chartTitle != null) { Map fontChanges = new HashMap<>(); fontChanges.put("CHART_TITLE", this.style.getTitleFont()); fontChanges.put("CHART_SUBTITLE", this.style.getSubtitleFont()); Map bgChanges = new HashMap<>(); bgChanges.put("CHART_TITLE", this.style.getTitleBackgroundColor()); bgChanges.put("CHART_SUBTITLE", this.style.getSubtitleBackgroundColor()); Map fgChanges = new HashMap<>(); fgChanges.put("CHART_TITLE", this.style.getTitleColor()); fgChanges.put("CHART_SUBTITLE", this.style.getSubtitleColor()); TableElementStyler m1 = new TableElementStyler(fontChanges, fgChanges, bgChanges); chartTitle.receive(m1); } chart.setChartBoxColor(this.style.getChartBoxColor()); } /** * Applies the current style to the plot. * * @param plot the plot ({@code null} not permitted). */ protected void stylePlot(Plot3D plot) { if (plot instanceof PiePlot3D) { PiePlot3D p = (PiePlot3D) plot; p.getSectionLabelFontSource().style( this.style.getSectionLabelFont()); p.getSectionLabelColorSource().style( this.style.getSectionLabelColor()); p.getSectionColorSource().style( this.style.getStandardColors()); } if (plot instanceof CategoryPlot3D) { CategoryPlot3D p = (CategoryPlot3D) plot; // gridline paint and stroke for rows, columns and values p.setGridlinesVisibleForColumns( this.style.getColumnAxisGridlinesVisible()); p.setGridlinesVisibleForRows( this.style.getRowAxisGridlinesVisible()); p.setGridlinesVisibleForValues( this.style.getYAxisGridlinesVisible()); p.setGridlinePaintForRows(this.style.getGridlineColor()); p.setGridlinePaintForColumns(this.style.getGridlineColor()); p.setGridlinePaintForValues(this.style.getGridlineColor()); p.setGridlineStrokeForColumns(this.style.getGridlineStroke()); p.setGridlineStrokeForRows(this.style.getGridlineStroke()); p.setGridlineStrokeForValues(this.style.getGridlineStroke()); } if (plot instanceof XYZPlot) { XYZPlot p = (XYZPlot) plot; p.setGridlinesVisibleX(this.style.getXAxisGridlinesVisible()); p.setGridlinesVisibleY(this.style.getYAxisGridlinesVisible()); p.setGridlinesVisibleZ(this.style.getZAxisGridlinesVisible()); p.setGridlinePaintX(this.style.getGridlineColor()); p.setGridlinePaintY(this.style.getGridlineColor()); p.setGridlinePaintZ(this.style.getGridlineColor()); p.setGridlineStrokeX(this.style.getGridlineStroke()); p.setGridlineStrokeY(this.style.getGridlineStroke()); p.setGridlineStrokeZ(this.style.getGridlineStroke()); } } /** * Applies the current style to the axis. * * @param axis the axis ({@code null} not permitted). */ protected void styleAxis(Axis3D axis) { // axis line visible, stroke and paint TODO // tick marks visible, stroke and paint TODO axis.setLabelFont(this.style.getAxisLabelFont()); axis.setLabelColor(this.style.getAxisLabelColor()); axis.setTickLabelFont(this.style.getAxisTickLabelFont()); axis.setTickLabelColor(this.style.getAxisTickLabelColor()); if (axis instanceof CategoryAxis3D) { styleCategoryAxis((CategoryAxis3D) axis); } if (axis instanceof ValueAxis3D) { styleValueAxis((ValueAxis3D) axis); } } /** * Applies the current style to a category axis. This implementation does * nothing, it is here for overriding. * * @param axis the axis ({@code null} not permitted). */ protected void styleCategoryAxis(CategoryAxis3D axis) { // for overriding } /** * Applies the current style to a value axis. This implementation does * nothing, it is here for overriding. * * @param axis the axis ({@code null} not permitted). */ protected void styleValueAxis(ValueAxis3D axis) { // for overriding } /** * Applies the current style to the renderer. * * @param renderer the renderer ({@code null} not permitted). */ protected void styleRenderer(Renderer3D renderer) { if (renderer instanceof CategoryRenderer3D) { styleCategoryRenderer3D((CategoryRenderer3D) renderer); } if (renderer instanceof XYZRenderer) { styleXYZRenderer((XYZRenderer) renderer); } } /** * Applies the current style to a category renderer. * * @param renderer the renderer ({@code null} not permitted). */ protected void styleCategoryRenderer3D(CategoryRenderer3D renderer) { renderer.getColorSource().style(this.style.getStandardColors()); } /** * Applies the current style to an XYZ renderer. * * @param renderer the renderer ({@code null} not permitted). */ protected void styleXYZRenderer(XYZRenderer renderer) { renderer.getColorSource().style(this.style.getStandardColors()); } /** * Applies the current style to a marker. * * @param marker the marker ({@code null} not permitted). */ protected void styleMarker(Marker marker) { if (marker instanceof CategoryMarker) { CategoryMarker cm = (CategoryMarker) marker; cm.setFont(this.style.getMarkerLabelFont()); cm.setLabelColor(this.style.getMarkerLabelColor()); cm.setLineColor(this.style.getMarkerLineColor()); cm.setLineStroke(this.style.getMarkerLineStroke()); cm.setFillColor(this.style.getMarkerFillColor()); } else if (marker instanceof NumberMarker) { NumberMarker nm = (NumberMarker) marker; nm.setFont(this.style.getMarkerLabelFont()); nm.setLabelColor(this.style.getMarkerLabelColor()); nm.setLineColor(this.style.getMarkerLineColor()); nm.setLineStroke(this.style.getMarkerLineStroke()); } else if (marker instanceof RangeMarker) { RangeMarker rm = (RangeMarker) marker; rm.setFont(this.style.getMarkerLabelFont()); rm.setLabelColor(this.style.getMarkerLabelColor()); rm.setFillColor(this.style.getMarkerFillColor()); rm.getStart().setFont(this.style.getMarkerLabelFont()); rm.getStart().setLabelColor(this.style.getMarkerLabelColor()); rm.getStart().setLineColor(this.style.getMarkerLineColor()); rm.getStart().setLineStroke(this.style.getMarkerLineStroke()); rm.getEnd().setFont(this.style.getMarkerLabelFont()); rm.getEnd().setLabelColor(this.style.getMarkerLabelColor()); rm.getEnd().setLineColor(this.style.getMarkerLineColor()); rm.getEnd().setLineStroke(this.style.getMarkerLineStroke()); } } } orson-charts-2.1.0/src/main/java/org/jfree/chart3d/style/ChartStyles.java000066400000000000000000000121141417331271500262550ustar00rootroot00000000000000/* =========================================================== * Orson Charts : a 3D chart library for the Java(tm) platform * =========================================================== * * (C)opyright 2013-2022, by David Gilbert. All rights reserved. * * https://github.com/jfree/orson-charts * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . * * [Oracle and Java are registered trademarks of Oracle and/or its affiliates. * Other names may be trademarks of their respective owners.] * * If you do not wish to be bound by the terms of the GPL, an alternative * commercial license can be purchased. For details, please see visit the * Orson Charts home page: * * http://www.object-refinery.com/orsoncharts/index.html * */ package org.jfree.chart3d.style; import java.awt.Color; import java.awt.Font; import org.jfree.chart3d.Colors; import org.jfree.chart3d.table.StandardRectanglePainter; /** * Some predefined chart styles. * * @since 1.2 */ public class ChartStyles { /** * Creates and returns a new instance of the "Orson 1" chart style. * * @return A chart style (never {@code null}). */ public static ChartStyle createOrson1Style() { StandardChartStyle s = new StandardChartStyle(); s.setStandardColors(Colors.createFancyLightColors()); return s; } /** * Creates and returns a new instance of the "Orson 2" chart style. This * style has a black background and uses shades of blue for the data * colors. * * @return A chart style (never {@code null}). */ public static ChartStyle createOrson2Style() { StandardChartStyle s = new StandardChartStyle(); Color bgcolor = new Color(50, 50, 50, 150); s.setTitleColor(Color.LIGHT_GRAY); s.setTitleBackgroundColor(bgcolor); s.setSubtitleColor(Color.LIGHT_GRAY); s.setSubtitleBackgroundColor(bgcolor); s.setChartBoxColor(new Color(200, 200, 255, 50)); s.setSectionLabelColor(Color.LIGHT_GRAY); s.setAxisLabelColor(Color.LIGHT_GRAY); s.setAxisTickLabelColor(Color.LIGHT_GRAY); s.setLegendHeaderColor(Color.LIGHT_GRAY); s.setLegendItemColor(Color.LIGHT_GRAY); s.setLegendHeaderBackgroundColor(bgcolor); s.setLegendItemBackgroundColor(bgcolor); s.setLegendFooterColor(Color.LIGHT_GRAY); s.setLegendFooterBackgroundColor(bgcolor); s.setStandardColors(Colors.createBlueOceanColors()); s.setBackgroundPainter(new StandardRectanglePainter(Color.BLACK)); s.setMarkerLabelColor(Color.LIGHT_GRAY); s.setMarkerLineColor(Color.LIGHT_GRAY); s.setMarkerFillColor(new Color(100, 100, 255, 32)); return s; } /** * Creates and returns a new instance of the "Pastel" chart style. * * @return A chart style (never {@code null}). */ public static ChartStyle createPastelStyle() { StandardChartStyle s = new StandardChartStyle(); s.setStandardColors(Colors.createPastelColors()); return s; } /** * Creates and returns a new instance of the "Pastel" chart style. * * @return A chart style (never {@code null}). */ public static ChartStyle createIceCubeStyle() { StandardChartStyle s = new StandardChartStyle(); s.setStandardColors(Colors.createIceCubeColors()); s.setBackgroundPainter(new StandardRectanglePainter(Color.WHITE)); return s; } /** * Creates and returns a new instance of the "Logical Font" chart style. * This style uses the Java logical fonts, but is otherwise the same as * the "Orson 1" chart style. * * @return A chart style (never {@code null}). */ public static ChartStyle createLogicalFontStyle() { StandardChartStyle s = new StandardChartStyle(); s.setTitleFont(new Font(Font.SANS_SERIF, Font.BOLD, 32)); s.setSubtitleFont(new Font(Font.SERIF, Font.PLAIN, 16)); s.setSectionLabelFont(new Font(Font.SERIF, Font.PLAIN, 16)); s.setAxisLabelFont(new Font(Font.SERIF, Font.BOLD, 16)); s.setAxisTickLabelFont(new Font(Font.SERIF, Font.PLAIN, 14)); s.setLegendHeaderFont(new Font(Font.SERIF, Font.BOLD, 16)); s.setLegendItemFont(new Font(Font.SERIF, Font.PLAIN, 14)); s.setLegendFooterFont(new Font(Font.SERIF, Font.ITALIC, 10)); s.setMarkerLabelFont(new Font(Font.SERIF, Font.PLAIN, 10)); s.setStandardColors(Colors.createFancyLightColors()); return s; } } orson-charts-2.1.0/src/main/java/org/jfree/chart3d/style/StandardChartStyle.java000066400000000000000000001376721417331271500275740ustar00rootroot00000000000000/* =========================================================== * Orson Charts : a 3D chart library for the Java(tm) platform * =========================================================== * * (C)opyright 2013-2022, by David Gilbert. All rights reserved. * * https://github.com/jfree/orson-charts * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . * * [Oracle and Java are registered trademarks of Oracle and/or its affiliates. * Other names may be trademarks of their respective owners.] * * If you do not wish to be bound by the terms of the GPL, an alternative * commercial license can be purchased. For details, please see visit the * Orson Charts home page: * * http://www.object-refinery.com/orsoncharts/index.html * */ package org.jfree.chart3d.style; import java.awt.BasicStroke; import java.awt.Color; import java.awt.Font; import java.awt.Stroke; import java.awt.Shape; import java.awt.geom.Rectangle2D; import java.io.IOException; import java.io.ObjectInputStream; import java.io.ObjectOutputStream; import java.io.Serializable; import java.util.Arrays; import javax.swing.event.EventListenerList; import org.jfree.chart3d.Colors; import org.jfree.chart3d.internal.Args; import org.jfree.chart3d.internal.ChartBox3D; import org.jfree.chart3d.internal.SerialUtils; import org.jfree.chart3d.table.RectanglePainter; import org.jfree.chart3d.table.StandardRectanglePainter; /** * A standard implementation of the {@link ChartStyle} interface. *

* NOTE: This class is serializable, but the serialization format is subject * to change in future releases and should not be relied upon for persisting * instances of this class. * * @since 1.2 */ @SuppressWarnings("serial") public class StandardChartStyle implements ChartStyle, Cloneable, Serializable { /** The first font family to try (usually found on Windows). */ private static final String FONT_FAMILY_1 = "Palatino Linotype"; /** The second font family to try (usually found on MacOSX). */ private static final String FONT_FAMILY_2 = "Palatino"; /** * Creates a default font with the specified {@code style} and * {@code size}. The method attempts to use 'Palatino Linotype' * ('Palatino' on MacOSX) but if it is not found it falls back to the * {@code Font.SERIF} font family. * * @param style the style (see java.awt.Font). * @param size the size. * * @return The font. * * @since 1.3 */ public static Font createDefaultFont(int style, int size) { Font f = new Font(FONT_FAMILY_1, style, size); if ("Dialog".equals(f.getFamily())) { f = new Font(FONT_FAMILY_2, style, size); if ("Dialog".equals(f.getFamily())) { f = new Font(Font.SERIF, style, size); } } return f; } /** * The default background color for the title and subtitle, and legend * header and footer. */ public static final Color DEFAULT_TEXT_BACKGROUND_COLOR = new Color(255, 255, 255, 100); /** The default title font. */ public static final Font DEFAULT_TITLE_FONT = createDefaultFont(Font.PLAIN, 32); /** The default subtitle font. */ public static final Font DEFAULT_SUBTITLE_FONT = createDefaultFont(Font.PLAIN, 18); /** The default chartbox color. */ public static final Color DEFAULT_CHARTBOX_COLOR = new Color(255, 255, 255, 100); /** The default visibility for gridlines perpendicular to the row-axis. */ public static final boolean DEFAULT_ROW_GRIDLINES_VISIBLE = false; /** The default visibility for gridlines perpendicular to the column-axis. */ public static final boolean DEFAULT_COLUMN_GRIDLINES_VISIBLE = false; /** The default visibility for gridlines perpendicular to the x-axis. */ public static final boolean DEFAULT_X_GRIDLINES_VISIBLE = true; /** The default visibility for gridlines perpendicular to the y-axis. */ public static final boolean DEFAULT_Y_GRIDLINES_VISIBLE = true; /** The default visibility for gridlines perpendicular to the z-axis. */ public static final boolean DEFAULT_Z_GRIDLINES_VISIBLE = true; /** The default gridline color. */ public static final Color DEFAULT_GRIDLINE_COLOR = Color.GRAY; /** The default gridline stroke. */ public static final Stroke DEFAULT_GRIDLINE_STROKE = new BasicStroke(0f); /** The default font for pie section labels. */ public static final Font DEFAULT_SECTION_LABEL_FONT = createDefaultFont( Font.PLAIN, 14); /** The default color for pie section labels. */ public static final Color DEFAULT_SECTION_LABEL_COLOR = Color.BLACK; /** The default font for axis labels. */ public static final Font DEFAULT_AXIS_LABEL_FONT = createDefaultFont(Font.BOLD, 12); /** The default foreground color for axis labels. */ public static final Color DEFAULT_AXIS_LABEL_COLOR = Color.BLACK; /** The default font for axis tick labels. */ public static final Font DEFAULT_AXIS_TICK_LABEL_FONT = createDefaultFont(Font.PLAIN, 12); /** The default foreground color for axis tick labels. */ public static final Color DEFAULT_AXIS_TICK_LABEL_COLOR = Color.BLACK; /** The default font for legend headers. */ public static final Font DEFAULT_LEGEND_HEADER_FONT = createDefaultFont( Font.BOLD, 14); /** The default foreground color for the legend header if there is one. */ public static final Color DEFAULT_LEGEND_HEADER_COLOR = Color.BLACK; /** The default legend item shape. */ public static final Shape DEFAULT_LEGEND_ITEM_SHAPE = new Rectangle2D.Double(-6, -4, 12, 8); /** The default font for legend item text. */ public static final Font DEFAULT_LEGEND_ITEM_FONT = createDefaultFont( Font.PLAIN, 12); /** The default legend item color. */ public static final Color DEFAULT_LEGEND_ITEM_COLOR = Color.BLACK; /** The default legend item background color. */ public static final Color DEFAULT_LEGEND_ITEM_BACKGROUND_COLOR = new Color(255, 255, 255, 100); /** The default font for legend footers. */ public static final Font DEFAULT_LEGEND_FOOTER_FONT = createDefaultFont( Font.PLAIN, 10); /** The default foreground color for the legend footer if there is one. */ public static final Color DEFAULT_LEGEND_FOOTER_COLOR = Color.BLACK; /** The default font for marker labels. */ public static final Font DEFAULT_MARKER_LABEL_FONT = createDefaultFont( Font.PLAIN, 10); /** The default foreground color for marker labels. */ public static final Color DEFAULT_MARKER_LABEL_COLOR = Color.DARK_GRAY; /** The default stroke for marker lines. */ public static final Stroke DEFAULT_MARKER_LINE_STROKE = new BasicStroke( 2.0f, BasicStroke.CAP_ROUND, BasicStroke.JOIN_ROUND); /** The default color for marker lines. */ public static final Color DEFAULT_MARKER_LINE_COLOR = Color.DARK_GRAY; /** The default fill color for markers. */ public static final Color DEFAULT_MARKER_FILL_COLOR = new Color(127, 127, 127, 63); /** The background painter. */ private RectanglePainter backgroundPainter; /** The chart title font. */ private Font titleFont; /** The foreground color for the chart title. */ private Color titleColor; /** The background color for the chart title. */ private Color titleBackgroundColor; /** The chart subtitle font. */ private Font subtitleFont; /** The foreground color for the chart subtitle. */ private Color subtitleColor; /** The background color for the chart subtitle. */ private Color subtitleBackgroundColor; /** The color for the chart box, if there is one. */ private Color chartBoxColor; /** Are gridlines visible for the row-axis? */ private boolean rowAxisGridlinesVisible; /** Are gridlines visible for the column-axis? */ private boolean columnAxisGridlinesVisible; /** Are gridlines visible for the x-axis? */ private boolean xAxisGridlinesVisible; /** Are gridlines visible for the y-axis? */ private boolean yAxisGridlinesVisible; /** Are gridlines visible for the z-axis? */ private boolean zAxisGridlinesVisible; /** The gridline color. */ private Color gridlineColor; /** The gridline stroke. */ private transient Stroke gridlineStroke; /** The font for pie section labels. */ private Font sectionLabelFont; /** The foreground color for pie section labels. */ private Color sectionLabelColor; /** The standard colors (to color pie sections or data series). */ private Color[] standardColors; /** The axis label font. */ private Font axisLabelFont; /** The color for the axis label. */ private Color axisLabelColor; /** The axis tick label font. */ private Font axisTickLabelFont; /** The color used to draw axis tick labels. */ private Color axisTickLabelColor; /** The legend header font. */ private Font legendHeaderFont; /** The legend header foreground color. */ private Color legendHeaderColor; /** The legend header background color. */ private Color legendHeaderBackgroundColor; /** The legend item shape. */ private Shape legendItemShape; /** The legend item font. */ private Font legendItemFont; /** The legend item color. */ private Color legendItemColor; /** The legend item background color. */ private Color legendItemBackgroundColor; /** The legend footer font. */ private Font legendFooterFont; /** The foreground color for the legend footer if there is one. */ private Color legendFooterColor; /** The background color for the legend footer if there is one. */ private Color legendFooterBackgroundColor; /** The font used to draw marker labels. */ private Font markerLabelFont; /** The color used to draw marker labels. */ private Color markerLabelColor; /** The stroke used to draw marker lines. */ private transient Stroke markerLineStroke; /** The color used to draw marker lines. */ private Color markerLineColor; /** The color used to fill the band representing the marker range. */ private Color markerFillColor; /** Storage for registered change listeners. */ private transient EventListenerList listenerList; /** * A flag that controls whether or not the chart will notify listeners * of changes (defaults to {@code true}, but sometimes it is useful * to disable this). */ private boolean notify; /** * Creates a new instance with default attributes. */ public StandardChartStyle() { this.backgroundPainter = new StandardRectanglePainter(Color.WHITE); this.titleFont = DEFAULT_TITLE_FONT; this.titleColor = Color.BLACK; this.titleBackgroundColor = DEFAULT_TEXT_BACKGROUND_COLOR; this.subtitleColor = Color.BLACK; this.subtitleBackgroundColor = DEFAULT_TEXT_BACKGROUND_COLOR; this.subtitleFont = DEFAULT_SUBTITLE_FONT; this.chartBoxColor = DEFAULT_CHARTBOX_COLOR; this.rowAxisGridlinesVisible = DEFAULT_ROW_GRIDLINES_VISIBLE; this.columnAxisGridlinesVisible = DEFAULT_COLUMN_GRIDLINES_VISIBLE; this.xAxisGridlinesVisible = DEFAULT_X_GRIDLINES_VISIBLE; this.yAxisGridlinesVisible = DEFAULT_Y_GRIDLINES_VISIBLE; this.zAxisGridlinesVisible = DEFAULT_Z_GRIDLINES_VISIBLE; this.gridlineColor = DEFAULT_GRIDLINE_COLOR; this.gridlineStroke = DEFAULT_GRIDLINE_STROKE; this.sectionLabelFont = DEFAULT_SECTION_LABEL_FONT; this.sectionLabelColor = DEFAULT_SECTION_LABEL_COLOR; this.standardColors = Colors.getDefaultColors(); this.axisLabelFont = DEFAULT_AXIS_LABEL_FONT; this.axisLabelColor = DEFAULT_AXIS_LABEL_COLOR; this.axisTickLabelFont = DEFAULT_AXIS_TICK_LABEL_FONT; this.axisTickLabelColor = DEFAULT_AXIS_TICK_LABEL_COLOR; this.legendHeaderFont = DEFAULT_LEGEND_HEADER_FONT; this.legendHeaderColor = DEFAULT_LEGEND_HEADER_COLOR; this.legendHeaderBackgroundColor = DEFAULT_TEXT_BACKGROUND_COLOR; this.legendItemShape = DEFAULT_LEGEND_ITEM_SHAPE; this.legendItemFont = DEFAULT_LEGEND_ITEM_FONT; this.legendItemColor = DEFAULT_LEGEND_ITEM_COLOR; this.legendItemBackgroundColor = DEFAULT_LEGEND_ITEM_BACKGROUND_COLOR; this.legendFooterFont = DEFAULT_LEGEND_FOOTER_FONT; this.legendFooterColor = DEFAULT_LEGEND_FOOTER_COLOR; this.legendFooterBackgroundColor = DEFAULT_TEXT_BACKGROUND_COLOR; this.markerLabelFont = DEFAULT_MARKER_LABEL_FONT; this.markerLabelColor = DEFAULT_MARKER_LABEL_COLOR; this.markerLineStroke = DEFAULT_MARKER_LINE_STROKE; this.markerLineColor = DEFAULT_MARKER_LINE_COLOR; this.markerFillColor = DEFAULT_MARKER_FILL_COLOR; this.listenerList = new EventListenerList(); this.notify = true; } /** * A copy constructor that creates a new style that is a copy of an * existing style (note that the existing style listeners are not copied). * * @param source the source style to copy ({@code null} not * permitted). */ public StandardChartStyle(StandardChartStyle source) { Args.nullNotPermitted(source, "source"); this.backgroundPainter = source.getBackgroundPainter(); this.titleFont = source.getTitleFont(); this.titleColor = source.getTitleColor(); this.titleBackgroundColor = source.getTitleBackgroundColor(); this.subtitleFont = source.getSubtitleFont(); this.subtitleColor = source.getSubtitleColor(); this.subtitleBackgroundColor = source.getSubtitleBackgroundColor(); this.chartBoxColor = source.getChartBoxColor(); this.xAxisGridlinesVisible = source.getXAxisGridlinesVisible(); this.yAxisGridlinesVisible = source.getYAxisGridlinesVisible(); this.zAxisGridlinesVisible = source.getZAxisGridlinesVisible(); this.sectionLabelFont = source.getSectionLabelFont(); this.sectionLabelColor = source.getSectionLabelColor(); this.standardColors = source.getStandardColors(); this.gridlineColor = source.getGridlineColor(); this.gridlineStroke = source.getGridlineStroke(); this.axisLabelFont = source.getAxisLabelFont(); this.axisLabelColor = source.getAxisLabelColor(); this.axisTickLabelFont = source.getAxisTickLabelFont(); this.axisTickLabelColor = source.getAxisTickLabelColor(); this.legendHeaderFont = source.getLegendHeaderFont(); this.legendHeaderColor = source.getLegendHeaderColor(); this.legendHeaderBackgroundColor = source.getLegendHeaderBackgroundColor(); this.legendItemShape = source.getLegendItemShape(); this.legendItemFont = source.getLegendItemFont(); this.legendItemColor = source.getLegendItemColor(); this.legendItemBackgroundColor = source.getLegendItemBackgroundColor(); this.legendFooterFont = source.getLegendFooterFont(); this.legendFooterColor = source.getLegendFooterColor(); this.legendFooterBackgroundColor = source.getLegendFooterBackgroundColor(); this.markerLabelFont = source.getMarkerLabelFont(); this.markerLabelColor = source.getMarkerLabelColor(); this.markerLineStroke = source.getMarkerLineStroke(); this.markerLineColor = source.getMarkerLineColor(); this.markerFillColor = source.getMarkerFillColor(); this.listenerList = new EventListenerList(); this.notify = true; } /** * Returns the background painter. * * @return The background painter (never {@code null}). */ @Override public RectanglePainter getBackgroundPainter() { return this.backgroundPainter; } /** * Sets the background painter. * * @param painter the painter ({@code null} not permitted). */ public void setBackgroundPainter(RectanglePainter painter) { Args.nullNotPermitted(painter, "painter"); this.backgroundPainter = painter; fireChangeEvent(); } /** * Returns the chart title font. The default value is * {@link #DEFAULT_TITLE_FONT}. * * @return The chart title font (never {@code null}). */ @Override public Font getTitleFont() { return this.titleFont; } /** * Sets the font used for the chart title and sends a * {@link ChartStyleChangeEvent} to all registered listeners. * * @param font the font ({@code null} not permitted). */ public void setTitleFont(Font font) { Args.nullNotPermitted(font, "font"); this.titleFont = font; fireChangeEvent(); } /** * Returns the title color. The default value is {@link Color#BLACK}. * * @return The title color (never {@code null}). */ @Override public Color getTitleColor() { return this.titleColor; } /** * Sets the foreground color for the chart title and sends a * change event to all registered listeners. * * @param color the color ({@code null} not permitted). */ public void setTitleColor(Color color) { this.titleColor = color; fireChangeEvent(); } /** * Returns the background color for the title. The default value is * {@link #DEFAULT_TEXT_BACKGROUND_COLOR}. * * @return The background color (never {@code null}). */ @Override public Color getTitleBackgroundColor() { return this.titleBackgroundColor; } /** * Sets the background color for the title and sends a * change event to all registered listeners. * * @param color the color ({@code null} not permitted). */ public void setTitleBackgroundColor(Color color) { this.titleBackgroundColor = color; fireChangeEvent(); } /** * Returns the font used for the chart subtitle. The default value * is {@link #DEFAULT_SUBTITLE_FONT}. * * @return The chart subtitle font (never {@code null}). */ @Override public Font getSubtitleFont() { return this.subtitleFont; } /** * Sets the font used for the chart subtitle and sends a * {@link ChartStyleChangeEvent} to all registered listeners. * * @param font the font ({@code null} not permitted). */ public void setSubtitleFont(Font font) { Args.nullNotPermitted(font, "font"); this.subtitleFont = font; fireChangeEvent(); } /** * Returns the color for the chart subtitle. The default value is * {@link Color#BLACK}. * * @return The color (never {@code null}). */ @Override public Color getSubtitleColor() { return this.subtitleColor; } /** * Sets the color for the chart subtitle and sends a * change event to all registered listeners. * * @param color the color ({@code null} not permitted). */ public void setSubtitleColor(Color color) { Args.nullNotPermitted(color, "color"); this.subtitleColor = color; fireChangeEvent(); } /** * Returns the background color for the chart subtitle. The default value * is {@link #DEFAULT_TEXT_BACKGROUND_COLOR}. * * @return The background color (never {@code null}). */ @Override public Color getSubtitleBackgroundColor() { return this.subtitleBackgroundColor; } /** * Sets the background color for the chart subtitle and sends a * change event to all registered listeners. * * @param color the color ({@code null} not permitted). */ public void setSubtitleBackgroundColor(Color color) { Args.nullNotPermitted(color, "color"); this.subtitleBackgroundColor = color; fireChangeEvent(); } /** * Returns the color used for the {@link ChartBox3D} (for those charts that * have one). The default value is {@link #DEFAULT_CHARTBOX_COLOR}. * * @return The color (never {@code null}). */ @Override public Color getChartBoxColor() { return this.chartBoxColor; } /** * Sets the color used for the chart box and sends a * {@link ChartStyleChangeEvent} to all registered listeners. * * @param color the color ({@code null} not permitted). */ public void setChartBoxColor(Color color) { Args.nullNotPermitted(color, "color"); this.chartBoxColor = color; fireChangeEvent(); } /** * Returns the flag that controls whether or not gridlines are drawn * perpendicular to the column axis in category plots. * * @return A boolean. */ @Override public boolean getColumnAxisGridlinesVisible() { return this.columnAxisGridlinesVisible; } /** * Returns the flag that controls whether or not gridlines are drawn * perpendicular to the row axis in category plots. * * @return A boolean. */ @Override public boolean getRowAxisGridlinesVisible() { return this.rowAxisGridlinesVisible; } /** * Returns the flag that specifies whether or not gridlines are drawn for * the x-axis. The default value is {@code false}. * * @return A boolean. */ @Override public boolean getXAxisGridlinesVisible() { return this.xAxisGridlinesVisible; } /** * Sets the flag that controls whether or not gridlines are drawn for * the x-axis and sends a {@link ChartStyleChangeEvent} to all * registered listeners. * * @param visible the new flag value. */ public void setXAxisGridlinesVisible(boolean visible) { this.xAxisGridlinesVisible = visible; fireChangeEvent(); } /** * Returns the flag that specifies whether or not gridlines are drawn for * the y-axis. The default value is {@code true}. * * @return A boolean. */ @Override public boolean getYAxisGridlinesVisible() { return this.yAxisGridlinesVisible; } /** * Sets the flag that controls whether or not gridlines are drawn for * the y-axis and sends a {@link ChartStyleChangeEvent} to all * registered listeners. * * @param visible the new flag value. */ public void setYAxisGridlinesVisible(boolean visible) { this.yAxisGridlinesVisible = visible; fireChangeEvent(); } /** * Returns the flag that specifies whether or not gridlines are drawn for * the z-axis. The default value is {@code true}. * * @return A boolean. */ @Override public boolean getZAxisGridlinesVisible() { return this.zAxisGridlinesVisible; } /** * Sets the flag that controls whether or not gridlines are drawn for * the z-axis and sends a {@link ChartStyleChangeEvent} to all * registered listeners. * * @param visible the new flag value. */ public void setZAxisGridlinesVisible(boolean visible) { this.zAxisGridlinesVisible = visible; fireChangeEvent(); } /** * Returns the color used for the gridlines. The default value is * {@link #DEFAULT_GRIDLINE_STROKE}. * * @return The color used for the gridlines (never {@code null}). */ @Override public Color getGridlineColor() { return this.gridlineColor; } /** * Sets the color for the gridlines and sends a * {@link ChartStyleChangeEvent} to all registered listeners. * * @param color the color ({@code null} not permitted). */ public void setGridlineColor(Color color) { Args.nullNotPermitted(color, "color"); this.gridlineColor = color; fireChangeEvent(); } /** * Returns the stroke used to draw the gridlines. The default value is * {@link #DEFAULT_GRIDLINE_STROKE}. * * @return The stroke (never {@code null}). */ @Override public Stroke getGridlineStroke() { return this.gridlineStroke; } /** * Sets the stroke used for gridlines and sends a * {@link ChartStyleChangeEvent} to all registered listeners. * * @param stroke the stroke ({@code null} not permitted). */ public void setGridlineStroke(Stroke stroke) { Args.nullNotPermitted(stroke, "stroke"); this.gridlineStroke = stroke; fireChangeEvent(); } /** * Returns the font used for pie section labels. The default value is * {@link #DEFAULT_SECTION_LABEL_FONT}. * * @return The font used for pie section labels (never {@code null}). */ @Override public Font getSectionLabelFont() { return this.sectionLabelFont; } /** * Sets the font used for the pie section labels and sends a * {@link ChartStyleChangeEvent} to all registered listeners. * * @param font the font ({@code null} not permitted). */ public void setSectionLabelFont(Font font) { Args.nullNotPermitted(font, "font"); this.sectionLabelFont = font; fireChangeEvent(); } /** * Returns the color used to display pie section labels. The default * value is {@link #DEFAULT_SECTION_LABEL_COLOR}. * * @return The color (never {@code null}). */ @Override public Color getSectionLabelColor() { return this.sectionLabelColor; } /** * Sets the color used for the pie section labels and sends a * {@link ChartStyleChangeEvent} to all registered listeners. * * @param color the color ({@code null} not permitted). */ public void setSectionLabelColor(Color color) { Args.nullNotPermitted(color, "color"); this.sectionLabelColor = color; fireChangeEvent(); } /** * Returns the standard colors for the style. The default value is * initialised by calling {@link Colors#getDefaultColors()}. * * @return The standard colors (never {@code null}). */ @Override public Color[] getStandardColors() { return this.standardColors; } /** * Sets the standard colors for the chart and sends a * {@link ChartStyleChangeEvent} to all registered listeners. * * @param colors the colors ({@code null} not permitted). */ public void setStandardColors(Color... colors) { this.standardColors = colors; fireChangeEvent(); } /** * Returns the font used for the axis label. The default value is * {@link #DEFAULT_AXIS_LABEL_FONT}. * * @return The font used for the axis label. */ @Override public Font getAxisLabelFont() { return this.axisLabelFont; } /** * Sets the font used for the axis label and sends a * {@link ChartStyleChangeEvent} to all registered listeners. * * @param font the font ({@code null} not permitted). */ public void setAxisLabelFont(Font font) { Args.nullNotPermitted(font, "font"); this.axisLabelFont = font; fireChangeEvent(); } /** * Returns the foreground color for the axis label (the main label, not * the tick labels). The default value is * {@link #DEFAULT_AXIS_LABEL_COLOR}. * * @return The color (never {@code null}). */ @Override public Color getAxisLabelColor() { return this.axisLabelColor; } /** * Sets the foreground color for the axis label and sends a * {@link ChartStyleChangeEvent} to all registered listeners. * * @param color the color ({@code null} not permitted). */ public void setAxisLabelColor(Color color) { Args.nullNotPermitted(color, "color"); this.axisLabelColor = color; fireChangeEvent(); } /** * Returns the font used for the axis tick labels. The default value * is {@link #DEFAULT_AXIS_TICK_LABEL_FONT}. * * @return The font (never {@code null}). */ @Override public Font getAxisTickLabelFont() { return this.axisTickLabelFont; } /** * Sets the font used for the axis tick labels and sends a * {@link ChartStyleChangeEvent} to all registered listeners. * * @param font the font ({@code null} not permitted). */ public void setAxisTickLabelFont(Font font) { Args.nullNotPermitted(font, "font"); this.axisTickLabelFont = font; fireChangeEvent(); } /** * Returns the color used to draw the tick labels on the axis. The * default value is {@link #DEFAULT_AXIS_TICK_LABEL_COLOR}. * * @return The color (never {@code null}). */ @Override public Color getAxisTickLabelColor() { return this.axisTickLabelColor; } /** * Sets the foreground color for the axis tick labels and sends a * {@link ChartStyleChangeEvent} to all registered listeners. * * @param color the color ({@code null} not permitted). */ public void setAxisTickLabelColor(Color color) { Args.nullNotPermitted(color, "color"); this.axisTickLabelColor = color; fireChangeEvent(); } /** * Returns the font used to display the legend header. The default * value is {@link #DEFAULT_LEGEND_HEADER_FONT}. * * @return The font (never {@code null}). */ @Override public Font getLegendHeaderFont() { return this.legendHeaderFont; } /** * Sets the legend header font and sends a {@link ChartStyleChangeEvent} to * all registered listeners. * * @param font the font ({@code null} not permitted). */ public void setLegendHeaderFont(Font font) { Args.nullNotPermitted(font, "font"); this.legendHeaderFont = font; fireChangeEvent(); } /** * Returns the foreground color for the legend header. The default value * is {@link #DEFAULT_LEGEND_HEADER_COLOR}. * * @return The color (never {@code null}). */ @Override public Color getLegendHeaderColor() { return this.legendHeaderColor; } /** * Sets the foreground color for the legend header and sends a * {@link ChartStyleChangeEvent} to all registered listeners. * * @param color the color ({@code null} not permitted). */ public void setLegendHeaderColor(Color color) { Args.nullNotPermitted(color, "color"); this.legendHeaderColor = color; fireChangeEvent(); } /** * Returns the background color for the legend header. The default value * is {@link #DEFAULT_TEXT_BACKGROUND_COLOR}. * * @return The color (never {@code null}). */ @Override public Color getLegendHeaderBackgroundColor() { return this.legendHeaderBackgroundColor; } /** * Sets the background color for the legend header and sends a * {@link ChartStyleChangeEvent} to all registered listeners. * * @param color the color ({@code null} not permitted). */ public void setLegendHeaderBackgroundColor(Color color) { Args.nullNotPermitted(color, "color"); this.legendHeaderBackgroundColor = color; fireChangeEvent(); } /** * Returns the standard shape for legend items. The default value * is {@link #DEFAULT_LEGEND_ITEM_SHAPE}. * * @return The legend shape (never {@code null}). */ @Override public Shape getLegendItemShape() { return this.legendItemShape; } /** * Sets the default shape for legend items and sends a * {@link ChartStyleChangeEvent} to all registered listeners. * * @param shape the shape ({@code null} not permitted). */ public void setLegendItemShape(Shape shape) { Args.nullNotPermitted(shape, "shape"); this.legendItemShape = shape; fireChangeEvent(); } /** * Returns the font used for legend item text. The default value is * {@link #DEFAULT_LEGEND_ITEM_FONT}. * * @return The font used for legend item text (never {@code null}). */ @Override public Font getLegendItemFont() { return this.legendItemFont; } /** * Sets the legend item font and sends a {@link ChartStyleChangeEvent} to * all registered listeners. * * @param font the font ({@code null} not permitted). */ public void setLegendItemFont(Font font) { Args.nullNotPermitted(font, "font"); this.legendItemFont = font; fireChangeEvent(); } /** * Returns the foreground color used for the legend items. The default * value is {@link #DEFAULT_LEGEND_ITEM_COLOR}. * * @return The color (never {@code null}). */ @Override public Color getLegendItemColor() { return this.legendItemColor; } /** * Sets the foreground color used for legend item text and sends a * {@link ChartStyleChangeEvent} to all registered listeners. * * @param color the color ({@code null} not permitted). */ public void setLegendItemColor(Color color) { Args.nullNotPermitted(color, "color"); this.legendItemColor = color; fireChangeEvent(); } /** * Returns the background color for legend items. The default value is * {@link #DEFAULT_LEGEND_ITEM_BACKGROUND_COLOR}. * * @return The color (never {@code null}). */ @Override public Color getLegendItemBackgroundColor() { return this.legendItemBackgroundColor; } /** * Sets the background color for legend items and sends a * {@link ChartStyleChangeEvent} to all registered listeners. * * @param color the color ({@code null} not permitted). */ public void setLegendItemBackgroundColor(Color color) { Args.nullNotPermitted(color, "color"); this.legendItemBackgroundColor = color; fireChangeEvent(); } /** * Returns the font for the legend footer. The default value is * {@link #DEFAULT_LEGEND_FOOTER_FONT}. * * @return The font (never {@code null}). */ @Override public Font getLegendFooterFont() { return this.legendFooterFont; } /** * Sets the legend footer font and sends a {@link ChartStyleChangeEvent} to * all registered listeners. * * @param font the font ({@code null} not permitted). */ public void setLegendFooterFont(Font font) { Args.nullNotPermitted(font, "font"); this.legendFooterFont = font; fireChangeEvent(); } /** * Returns the foreground color for the legend footer. The default * value is {@link #DEFAULT_LEGEND_FOOTER_COLOR}. * * @return The color (never {@code null}). */ @Override public Color getLegendFooterColor() { return this.legendFooterColor; } /** * Sets the foreground color for the legend footer and sends a * {@link ChartStyleChangeEvent} to all registered listeners. * * @param color the color ({@code null} not permitted). */ public void setLegendFooterColor(Color color) { Args.nullNotPermitted(color, "color"); this.legendFooterColor = color; fireChangeEvent(); } /** * Returns the background color for the legend footer. The default * value is {@link #DEFAULT_TEXT_BACKGROUND_COLOR}. * * @return The color (never {@code null}). */ @Override public Color getLegendFooterBackgroundColor() { return this.legendFooterBackgroundColor; } /** * Sets the background color for the legend footer and sends a * {@link ChartStyleChangeEvent} to all registered listeners. * * @param color the color ({@code null} not permitted). */ public void setLegendFooterBackgroundColor(Color color) { Args.nullNotPermitted(color, "color"); this.legendFooterBackgroundColor = color; fireChangeEvent(); } /** * Returns the font used to draw marker labels. * * @return The font used to draw marker labels (never {@code null}). */ @Override public Font getMarkerLabelFont() { return this.markerLabelFont; } /** * Sets the marker label font and sends a change event to all registered * listeners. * * @param font the font ({@code null} not permitted). */ public void setMarkerLabelFont(Font font) { Args.nullNotPermitted(font, "font"); this.markerLabelFont = font; fireChangeEvent(); } /** * Returns the color for the marker labels. * * @return The color for the marker labels (never {@code null}). */ @Override public Color getMarkerLabelColor() { return this.markerLabelColor; } /** * Sets the color for the marker labels and sends a change event to all * registered listeners. * * @param color the color ({@code null} not permitted). */ public void setMarkerLabelColor(Color color) { Args.nullNotPermitted(color, "color"); this.markerLabelColor = color; fireChangeEvent(); } /** * Returns the stroke used to draw marker lines. * * @return The stroke used to draw marker lines (never {@code null}). */ @Override public Stroke getMarkerLineStroke() { return this.markerLineStroke; } /** * Sets the stroke for the marker lines and sends a change event to all * registered listeners. * * @param stroke the stroke ({@code null} not permitted). */ public void setMarkerLineStroke(Stroke stroke) { Args.nullNotPermitted(stroke, "stroke"); this.markerLineStroke = stroke; fireChangeEvent(); } /** * Returns the color used to draw marker lines. * * @return The color used to draw marker lines (never {@code null}). */ @Override public Color getMarkerLineColor() { return markerLineColor; } /** * Sets the marker line color and sends a change event to all registered * listeners. * * @param color the color ({@code null} not permitted). */ public void setMarkerLineColor(Color color) { Args.nullNotPermitted(color, "color"); this.markerLineColor = color; fireChangeEvent(); } /** * Returns the color used to fill the band representing the marker range. * * @return The fill color (never {@code null}). */ @Override public Color getMarkerFillColor() { return markerFillColor; } /** * Sets the marker fill color and sends a change event to all registered * listeners. * * @param color the color ({@code null} not permitted). */ public void setMarkerFillColor(Color color) { Args.nullNotPermitted(color, "color"); this.markerFillColor = color; fireChangeEvent(); } /** * Registers a listener to receive notification of changes to the chart. * When a style is added to a chart, the chart will register as a listener * on the style. * * @param listener the listener. */ @Override public void addChangeListener(ChartStyleChangeListener listener) { this.listenerList.add(ChartStyleChangeListener.class, listener); } /** * Deregisters a listener so that it no longer receives notification of * changes to the chart. * * @param listener the listener. */ @Override public void removeChangeListener(ChartStyleChangeListener listener) { this.listenerList.remove(ChartStyleChangeListener.class, listener); } /** * Notifies all registered listeners that the chart style has been modified. * * @param event information about the change event. */ public void notifyListeners(ChartStyleChangeEvent event) { // if the 'notify' flag has been switched to false, we don't notify // the listeners if (!this.notify) { return; } Object[] listeners = this.listenerList.getListenerList(); for (int i = listeners.length - 2; i >= 0; i -= 2) { if (listeners[i] == ChartStyleChangeListener.class) { ((ChartStyleChangeListener) listeners[i + 1]).styleChanged(event); } } } /** * Returns a flag that controls whether or not change events are sent to * registered listeners. * * @return A boolean. * * @see #setNotify(boolean) */ public boolean isNotify() { return this.notify; } /** * Sets a flag that controls whether or not listeners receive * {@link ChartStyleChangeEvent} notifications. This can be useful when * updating multiple style attributes, you can call setNotify(false) first, * update the styles, then call setNotify(true) at the end. * * @param notify a boolean. * * @see #isNotify() */ public void setNotify(boolean notify) { this.notify = notify; // if the flag is being set to true, there may be queued up changes... if (notify) { fireChangeEvent(); } } /** * Sends a {@link ChartStyleChangeEvent} to all registered listeners. */ protected void fireChangeEvent() { notifyListeners(new ChartStyleChangeEvent(this, this)); } /** * Returns a clone of the chart style (note that the change listeners * are not cloned). * * @return A clone (never {@code null}). */ @Override public ChartStyle clone() { try { return (ChartStyle) super.clone(); } catch (CloneNotSupportedException e) { throw new IllegalStateException( "If we get here, a bug needs fixing."); } } /** * Tests this instance for equality with an arbitrary object. * * @param obj the object ({@code null} permitted). * * @return A boolean. */ @Override public boolean equals(Object obj) { if (obj == this) { return true; } if (!(obj instanceof StandardChartStyle)) { return false; } StandardChartStyle that = (StandardChartStyle) obj; if (!this.backgroundPainter.equals(that.backgroundPainter)) { return false; } if (!this.titleFont.equals(that.titleFont)) { return false; } if (!this.titleColor.equals(that.titleColor)) { return false; } if (!this.titleBackgroundColor.equals(that.titleBackgroundColor)) { return false; } if (!this.subtitleFont.equals(that.subtitleFont)) { return false; } if (!this.subtitleColor.equals(that.subtitleColor)) { return false; } if (!this.subtitleBackgroundColor.equals( that.subtitleBackgroundColor)) { return false; } if (!this.chartBoxColor.equals(that.chartBoxColor)) { return false; } if (this.rowAxisGridlinesVisible!= that.rowAxisGridlinesVisible) { return false; } if (this.columnAxisGridlinesVisible != that.columnAxisGridlinesVisible) { return false; } if (this.xAxisGridlinesVisible != that.xAxisGridlinesVisible) { return false; } if (this.yAxisGridlinesVisible != that.yAxisGridlinesVisible) { return false; } if (this.zAxisGridlinesVisible != that.zAxisGridlinesVisible) { return false; } if (!this.gridlineColor.equals(that.gridlineColor)) { return false; } if (!this.gridlineStroke.equals(that.gridlineStroke)) { return false; } if (!this.sectionLabelFont.equals(that.sectionLabelFont)) { return false; } if (!this.sectionLabelColor.equals(that.sectionLabelColor)) { return false; } if (!Arrays.equals(this.standardColors, that.standardColors)) { return false; } if (!this.axisLabelFont.equals(that.axisLabelFont)) { return false; } if (!this.axisLabelColor.equals(that.axisLabelColor)) { return false; } if (!this.axisTickLabelFont.equals(that.axisTickLabelFont)) { return false; } if (!this.axisTickLabelColor.equals(that.axisTickLabelColor)) { return false; } if (!this.legendHeaderFont.equals(that.legendHeaderFont)) { return false; } if (!this.legendHeaderColor.equals(that.legendHeaderColor)) { return false; } if (!this.legendHeaderBackgroundColor.equals( that.legendHeaderBackgroundColor)) { return false; } if (!this.legendItemShape.equals(that.legendItemShape)) { return false; } if (!this.legendItemFont.equals(that.legendItemFont)) { return false; } if (!this.legendItemColor.equals(that.legendItemColor)) { return false; } if (!this.legendItemBackgroundColor.equals( that.legendItemBackgroundColor)) { return false; } if (!this.legendFooterFont.equals(that.legendFooterFont)) { return false; } if (!this.legendFooterColor.equals(that.legendFooterColor)) { return false; } if (!this.legendFooterBackgroundColor.equals( that.legendFooterBackgroundColor)) { return false; } if (!this.markerLabelFont.equals(that.markerLabelFont)) { return false; } if (!this.markerLabelColor.equals(that.markerLabelColor)) { return false; } if (!this.markerLineColor.equals(that.markerLineColor)) { return false; } if (!this.markerLineStroke.equals(that.markerLineStroke)) { return false; } if (!this.markerFillColor.equals(that.markerFillColor)) { return false; } return true; } /** * Provides serialization support. * * @param stream the output stream. * * @throws IOException if there is an I/O error. */ private void writeObject(ObjectOutputStream stream) throws IOException { stream.defaultWriteObject(); SerialUtils.writeStroke(this.gridlineStroke, stream); SerialUtils.writeStroke(this.markerLineStroke, stream); } /** * Provides serialization support. * * @param stream the input stream. * * @throws IOException if there is an I/O error. * @throws ClassNotFoundException if there is a classpath problem. */ private void readObject(ObjectInputStream stream) throws IOException, ClassNotFoundException { stream.defaultReadObject(); this.gridlineStroke = SerialUtils.readStroke(stream); this.markerLineStroke = SerialUtils.readStroke(stream); } } orson-charts-2.1.0/src/main/java/org/jfree/chart3d/style/package-info.java000066400000000000000000000001221417331271500263300ustar00rootroot00000000000000/** * Classes for controlling chart styles. */ package org.jfree.chart3d.style; orson-charts-2.1.0/src/main/java/org/jfree/chart3d/table/000077500000000000000000000000001417331271500230755ustar00rootroot00000000000000orson-charts-2.1.0/src/main/java/org/jfree/chart3d/table/AbstractTableElement.java000066400000000000000000000171441417331271500277740ustar00rootroot00000000000000/* =========================================================== * Orson Charts : a 3D chart library for the Java(tm) platform * =========================================================== * * (C)opyright 2013-2022, by David Gilbert. All rights reserved. * * https://github.com/jfree/orson-charts * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . * * [Oracle and Java are registered trademarks of Oracle and/or its affiliates. * Other names may be trademarks of their respective owners.] * * If you do not wish to be bound by the terms of the GPL, an alternative * commercial license can be purchased. For details, please see visit the * Orson Charts home page: * * http://www.object-refinery.com/orsoncharts/index.html * */ package org.jfree.chart3d.table; import java.awt.Color; import java.awt.Graphics2D; import java.awt.Insets; import java.awt.geom.Dimension2D; import java.awt.geom.Rectangle2D; import java.io.Serializable; import java.util.HashMap; import java.util.Map; import org.jfree.chart3d.graphics2d.RefPt2D; import org.jfree.chart3d.internal.Args; import org.jfree.chart3d.internal.ObjectUtils; /** * A base class that can be used to implement a {@link TableElement}. *

* NOTE: This class is serializable, but the serialization format is subject * to change in future releases and should not be relied upon for persisting * instances of this class. */ @SuppressWarnings("serial") public abstract class AbstractTableElement implements Serializable { /** The default background color. */ private static final Color DEFAULT_BACKGROUND_COLOR = new Color(255, 255, 255, 127); /** The reference point used to align the element when rendering. */ private RefPt2D refPt; /** The insets. */ private Insets insets; /** The background paint (this can be {@code null}). */ private RectanglePainter background; /** A tag that can be used to identify the class of element. */ private String tag; /** Stores properties for the element. */ private final HashMap properties; /** * Creates a new instance. */ public AbstractTableElement() { this.refPt = RefPt2D.CENTER; this.insets = new Insets(2, 2, 2, 2); this.background = new StandardRectanglePainter( DEFAULT_BACKGROUND_COLOR); this.tag = ""; this.properties = new HashMap<>(); } /** * Returns the anchor point used to align the element with the bounding * rectangle within which it is drawn. The default value is * {@link RefPt2D#CENTER}. * * @return The anchor point (never {@code null}). * * @since 1.1 */ public RefPt2D getRefPoint() { return this.refPt; } /** * Sets the reference point. * * @param refPt the reference point ({@code null} not permitted). * * @since 1.1 */ public void setRefPoint(RefPt2D refPt) { Args.nullNotPermitted(refPt, "refPt"); this.refPt = refPt; } /** * Returns the insets. The default value is {@code Insets(2, 2, 2, 2)}. * * @return The insets (never {@code null}). */ public Insets getInsets() { return this.insets; } /** * Sets the insets. * * @param insets the insets ({@code null} not permitted). */ public void setInsets(Insets insets) { Args.nullNotPermitted(insets, "insets"); this.insets = insets; } /** * Returns the background painter for the element. * * @return The background painter (possibly {@code null}). */ public RectanglePainter getBackground() { return this.background; } /** * Sets the background for the element. * * @param background the new background ({@code null} permitted). */ public void setBackground(RectanglePainter background) { this.background = background; } /** * Sets the background painter to fill the element with the specified * color. If the color is {@code null}, the background painter will * be set to {@code null}. * * @param color the color ({@code null} permitted). * * @since 1.2 */ public void setBackgroundColor(Color color) { if (color != null) { this.background = new StandardRectanglePainter(color); } else { this.background = null; } } /** * Returns the tag for this element. The default value is an empty string. * * @return The tag (never {@code null}). * * @since 1.2 */ public String getTag() { return this.tag; } /** * Sets the tag. * * @param tag the tag ({@code null} not permitted). * * @since 1.2 */ public void setTag(String tag) { Args.nullNotPermitted(tag, "tag"); this.tag = tag; } /** * Returns the value of the property with the specified key, or * {@code null}. * * @param key the key ({@code null} not permitted). * * @return The property value or {@code null}. * * @since 1.3 */ public Object getProperty(String key) { return this.properties.get(key); } /** * Sets the value of the property with the specified key. * * @param key the key ({@code null} not permitted). * @param value the value ({@code null} permitted). * * @since 1.3 */ public void setProperty(String key, Object value) { Args.nullNotPermitted(key, "key"); this.properties.put(key, value); } /** * Returns the preferred size of the element (including insets). * * @param g2 the graphics target. * @param bounds the bounds. * * @return The preferred size. */ public Dimension2D preferredSize(Graphics2D g2, Rectangle2D bounds) { return preferredSize(g2, bounds, null); } /** * Returns the preferred size of the element (including insets). * * @param g2 the graphics target. * @param bounds the bounds. * @param constraints the constraints (ignored for now). * * @return The preferred size. */ public abstract Dimension2D preferredSize(Graphics2D g2, Rectangle2D bounds, Map constraints); /** * Tests this instance for equality with an arbitrary object. * * @param obj the object ({@code null} permitted). * * @return A boolean. */ @Override public boolean equals(Object obj) { if (obj == this) { return true; } if (!(obj instanceof AbstractTableElement)) { return false; } AbstractTableElement that = (AbstractTableElement) obj; if (!this.insets.equals(that.insets)) { return false; } if (!ObjectUtils.equals(this.background, that.background)) { return false; } return true; } } orson-charts-2.1.0/src/main/java/org/jfree/chart3d/table/ContainerElement.java000066400000000000000000000033461417331271500272020ustar00rootroot00000000000000/* =========================================================== * Orson Charts : a 3D chart library for the Java(tm) platform * =========================================================== * * (C)opyright 2013-2022, by David Gilbert. All rights reserved. * * https://github.com/jfree/orson-charts * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . * * [Oracle and Java are registered trademarks of Oracle and/or its affiliates. * Other names may be trademarks of their respective owners.] * * If you do not wish to be bound by the terms of the GPL, an alternative * commercial license can be purchased. For details, please see visit the * Orson Charts home page: * * http://www.object-refinery.com/orsoncharts/index.html * */ package org.jfree.chart3d.table; /** * A {@link TableElement} that contains other elements (provides the * {@code addElement()} method). * * @since 1.1 */ public interface ContainerElement extends TableElement { /** * Adds a sub-element to the container element. * * @param element the element ({@code null} not permitted). */ void addElement(TableElement element); } orson-charts-2.1.0/src/main/java/org/jfree/chart3d/table/ElementDimension.java000066400000000000000000000072521417331271500272050ustar00rootroot00000000000000/* =========================================================== * Orson Charts : a 3D chart library for the Java(tm) platform * =========================================================== * * (C)opyright 2013-2022, by David Gilbert. All rights reserved. * * https://github.com/jfree/orson-charts * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . * * [Oracle and Java are registered trademarks of Oracle and/or its affiliates. * Other names may be trademarks of their respective owners.] * * If you do not wish to be bound by the terms of the GPL, an alternative * commercial license can be purchased. For details, please see visit the * Orson Charts home page: * * http://www.object-refinery.com/orsoncharts/index.html * */ package org.jfree.chart3d.table; import java.awt.geom.Dimension2D; import java.io.Serializable; /** * An element dimension (in fact a simple implementation of the * {@code Dimension2D} interface). *

* NOTE: This class is serializable, but the serialization format is subject * to change in future releases and should not be relied upon for persisting * instances of this class. */ @SuppressWarnings("serial") public final class ElementDimension extends Dimension2D implements Serializable { /** The width (in Java2D units). */ private double width; /** The height (in Java2D units). */ private double height; /** * Creates a new dimension object. * * @param width the width. * @param height the height. */ public ElementDimension(double width, double height) { super(); this.width = width; this.height = height; } /** * Returns the width. * * @return The width. */ @Override public double getWidth() { return this.width; } /** * Returns the height. * * @return The height. */ @Override public double getHeight() { return this.height; } /** * Sets the size. * * @param width the width. * @param height the height. */ @Override public void setSize(double width, double height) { this.width = width; this.height = height; } /** * Tests this dimension for equality with an arbitrary object. * * @param obj the object ({@code null} permitted). * * @return A boolean. */ @Override public boolean equals(Object obj) { if (obj == this) { return true; } if (!(obj instanceof ElementDimension)) { return false; } ElementDimension that = (ElementDimension) obj; if (this.width != that.width) { return false; } if (this.height != that.height) { return false; } return true; } /** * Returns a string representation of this dimension, primarily for * debugging purposes. * * @return A string. */ @Override public String toString() { return "ElementDimension(" + this.width + ", " + this.height + ")"; } } orson-charts-2.1.0/src/main/java/org/jfree/chart3d/table/ElementInfo.java000066400000000000000000000050071417331271500261470ustar00rootroot00000000000000/* =========================================================== * Orson Charts : a 3D chart library for the Java(tm) platform * =========================================================== * * (C)opyright 2013-2022, by David Gilbert. All rights reserved. * * https://github.com/jfree/orson-charts * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . * * [Oracle and Java are registered trademarks of Oracle and/or its affiliates. * Other names may be trademarks of their respective owners.] * * If you do not wish to be bound by the terms of the GPL, an alternative * commercial license can be purchased. For details, please see visit the * Orson Charts home page: * * http://www.object-refinery.com/orsoncharts/index.html * */ package org.jfree.chart3d.table; import java.awt.geom.Dimension2D; import org.jfree.chart3d.internal.Args; /** * An object that pairs an element with its dimension for one specific * graphics target. * * @since 1.1 */ public class ElementInfo { /** The element. */ private TableElement element; /** The element's size. */ private Dimension2D dimension; /** * Creates a new instance. * * @param element the element ({@code null} not permitted). * @param dimension the dimension ({@code null} not permitted). */ public ElementInfo(TableElement element, Dimension2D dimension) { Args.nullNotPermitted(element, "element"); Args.nullNotPermitted(dimension, "dimension"); this.element = element; this.dimension = dimension; } /** * Returns the element. * * @return The element (never {@code null}). */ public TableElement getElement() { return this.element; } /** * Returns the element's size. * * @return The element's size (never {@code null}). */ public Dimension2D getDimension() { return this.dimension; } } orson-charts-2.1.0/src/main/java/org/jfree/chart3d/table/FlowElement.java000066400000000000000000000314141417331271500261640ustar00rootroot00000000000000/* =========================================================== * Orson Charts : a 3D chart library for the Java(tm) platform * =========================================================== * * (C)opyright 2013-2022, by David Gilbert. All rights reserved. * * https://github.com/jfree/orson-charts * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . * * [Oracle and Java are registered trademarks of Oracle and/or its affiliates. * Other names may be trademarks of their respective owners.] * * If you do not wish to be bound by the terms of the GPL, an alternative * commercial license can be purchased. For details, please see visit the * Orson Charts home page: * * http://www.object-refinery.com/orsoncharts/index.html * */ package org.jfree.chart3d.table; import java.awt.Insets; import java.awt.Graphics2D; import java.awt.Shape; import java.awt.geom.Dimension2D; import java.awt.geom.Rectangle2D; import java.io.Serializable; import java.util.ArrayList; import java.util.List; import java.util.Map; import org.jfree.chart3d.graphics2d.Fit2D; import org.jfree.chart3d.internal.Args; /** * A table element that displays a list of sub-elements in a flow layout. *

* NOTE: This class is serializable, but the serialization format is subject * to change in future releases and should not be relied upon for persisting * instances of this class. */ @SuppressWarnings("serial") public class FlowElement extends AbstractTableElement implements ContainerElement, Serializable { /** The sub-elements in this flow. */ private List elements; /** The horizontal alignment of each row. */ private HAlign horizontalAlignment; /** * The horizontal gap between elements on the same line, specified in * Java2D units. */ private int hgap; /** * Creates a new instance (equivalent to * {@code new FlowElement(HAlign.CENTER, 2)}). */ public FlowElement() { this(HAlign.CENTER, 2); } /** * Creates a new instance with the specified attributes. * * @param alignment the horizontal alignment of the elements within * each row ({@code null} not permitted). * @param hgap the gap between elements. * * @since 1.1 */ public FlowElement(HAlign alignment, int hgap) { super(); Args.nullNotPermitted(alignment, "alignment"); this.elements = new ArrayList<>(); this.horizontalAlignment = alignment; this.hgap = hgap; } /** * Returns the horizontal gap between elements, specified in Java2D units. * The default value is {@code 2}. * * @return The horizontal gap. */ public int getHGap() { return this.hgap; } /** * Sets the horizontal gap between elements. * * @param gap the gap (in Java2D units). */ public void setHGap(int gap) { this.hgap = gap; } /** * Returns the horizontal alignment of items within rows. The default * value is {@link HAlign#CENTER}. * * @return The horizontal alignment (never {@code null}). * * @since 1.1 */ public HAlign getHorizontalAlignment() { return this.horizontalAlignment; } /** * Sets the horizontal alignment. * * @param alignment the alignment ({@code null} not permitted). * * @since 1.1 */ public void setHorizontalAlignment(HAlign alignment) { Args.nullNotPermitted(alignment, "alignment"); this.horizontalAlignment = alignment; } /** * Returns a (new) list containing the elements in this flow layout. * * @return A list containing the elements (possibly empty, but never * {@code null}). */ public List getElements() { return new ArrayList<>(this.elements); } /** * Adds a sub-element to the list. * * @param element the element ({@code null} not permitted). */ @Override public void addElement(TableElement element) { Args.nullNotPermitted(element, "element"); this.elements.add(element); } /** * Receives a visitor. The implementation ensures that the vistor visits * all the elements belonging to the flow. * * @param visitor the visitor ({@code null} not permitted). * * @since 1.2 */ @Override public void receive(TableElementVisitor visitor) { for (TableElement element : elements) { element.receive(visitor); } } /** * Returns info for as many elements as we can fit into one row. * * @param first the index of the first element. * @param g2 the graphics target. * @param bounds the bounds. * * @return A list of elements and dimensions. */ private List rowOfElements(int first, Graphics2D g2, Rectangle2D bounds) { List result = new ArrayList<>(); int index = first; boolean full = false; double w = getInsets().left + getInsets().right; while (index < this.elements.size() && !full) { TableElement element = this.elements.get(index); Dimension2D dim = element.preferredSize(g2, bounds); if (w + dim.getWidth() <= bounds.getWidth() || index == first) { result.add(new ElementInfo(element, dim)); w += dim.getWidth() + this.hgap; index++; } else { full = true; } } return result; } /** * Returns the height of the tallest element in the list. * * @param elementInfoList element info list * * @return The height. */ private double calcRowHeight(List elementInfoList) { double result = 0.0; for (ElementInfo elementInfo : elementInfoList) { result = Math.max(result, elementInfo.getDimension().getHeight()); } return result; } /** * Calculates the total width of the elements that will form one row. * * @param elementInfoList the elements in the column. * @param hgap the gap between elements. * * @return The total height. */ private double calcRowWidth(List elementInfoList, double hgap) { double result = 0.0; for (ElementInfo elementInfo : elementInfoList) { result += elementInfo.getDimension().getWidth(); } int count = elementInfoList.size(); if (count > 1) { result += (count - 1) * hgap; } return result; } /** * Returns the preferred size of the element (including insets). * * @param g2 the graphics target. * @param bounds the bounds. * @param constraints the constraints (ignored for now). * * @return The preferred size. */ @Override public Dimension2D preferredSize(Graphics2D g2, Rectangle2D bounds, Map constraints) { Insets insets = getInsets(); double width = insets.left + insets.right; double height = insets.top + insets.bottom; double maxRowWidth = 0.0; int elementCount = this.elements.size(); int i = 0; while (i < elementCount) { // get one row of elements... List elementsInRow = rowOfElements(i, g2, bounds); double rowHeight = calcRowHeight(elementsInRow); double rowWidth = calcRowWidth(elementsInRow, this.hgap); maxRowWidth = Math.max(rowWidth, maxRowWidth); height += rowHeight; i = i + elementsInRow.size(); } width += maxRowWidth; return new ElementDimension(width, height); } /** * Calculates the layout of the elements for the given bounds and * constraints. * * @param g2 the graphics target ({@code null} not permitted). * @param bounds the bounds ({@code null} not permitted). * @param constraints the constraints (not used here). * * @return A list of positions for the sub-elements. */ @Override public List layoutElements(Graphics2D g2, Rectangle2D bounds, Map constraints) { int elementCount = this.elements.size(); List result = new ArrayList<>(elementCount); int i = 0; double x = bounds.getX() + getInsets().left; double y = bounds.getY() + getInsets().top; while (i < elementCount) { // get one row of elements... List elementsInRow = rowOfElements(i, g2, bounds); double height = calcRowHeight(elementsInRow); double width = calcRowWidth(elementsInRow, this.hgap); if (this.horizontalAlignment == HAlign.CENTER) { x = bounds.getCenterX() - (width / 2.0); } else if (this.horizontalAlignment == HAlign.RIGHT) { x = bounds.getMaxX() - getInsets().right - width; } for (ElementInfo elementInfo : elementsInRow) { Dimension2D dim = elementInfo.getDimension(); Rectangle2D position = new Rectangle2D.Double(x, y, dim.getWidth(), height); result.add(position); x += position.getWidth() + this.hgap; } i = i + elementsInRow.size(); x = bounds.getX() + getInsets().left; y += height; } return result; } /** * Draws the element within the specified bounds. * * @param g2 the graphics target ({@code null} not permitted). * @param bounds the bounds ({@code null} not permitted). */ @Override public void draw(Graphics2D g2, Rectangle2D bounds) { draw(g2, bounds, null); } /** * Draws the element within the specified bounds. * * @param g2 the graphics target ({@code null} not permitted). * @param bounds the bounds ({@code null} not permitted). * @param onDrawHandler an object that will receive notification before * and after the element is drawn ({@code null} permitted). * * @since 1.3 */ @Override public void draw(Graphics2D g2, Rectangle2D bounds, TableElementOnDraw onDrawHandler) { if (onDrawHandler != null) { onDrawHandler.beforeDraw(this, g2, bounds); } Shape savedClip = g2.getClip(); g2.clip(bounds); // find the preferred size of the flow layout Dimension2D prefDim = preferredSize(g2, bounds); // fit a rectangle of this dimension to the bounds according to the // element anchor Fit2D fitter = Fit2D.getNoScalingFitter(getRefPoint()); Rectangle2D dest = fitter.fit(prefDim, bounds); // perform layout within this bounding rectangle List layoutInfo = this.layoutElements(g2, dest, null); // draw the elements for (int i = 0; i < this.elements.size(); i++) { Rectangle2D rect = layoutInfo.get(i); TableElement element = this.elements.get(i); element.draw(g2, rect, onDrawHandler); } g2.setClip(savedClip); if (onDrawHandler != null) { onDrawHandler.afterDraw(this, g2, bounds); } } /** * Tests this element for equality with an arbitrary object. * * @param obj the object ({@code null} permitted). * * @return A boolean. */ @Override public boolean equals(Object obj) { if (obj == this) { return true; } if (!(obj instanceof FlowElement)) { return false; } FlowElement that = (FlowElement) obj; if (this.hgap != that.hgap) { return false; } if (this.horizontalAlignment != that.horizontalAlignment) { return false; } if (!this.elements.equals(that.elements)) { return false; } return super.equals(obj); } } orson-charts-2.1.0/src/main/java/org/jfree/chart3d/table/GradientRectanglePainter.java000066400000000000000000000164321417331271500306530ustar00rootroot00000000000000/* =========================================================== * Orson Charts : a 3D chart library for the Java(tm) platform * =========================================================== * * (C)opyright 2013-2022, by David Gilbert. All rights reserved. * * https://github.com/jfree/orson-charts * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . * * [Oracle and Java are registered trademarks of Oracle and/or its affiliates. * Other names may be trademarks of their respective owners.] * * If you do not wish to be bound by the terms of the GPL, an alternative * commercial license can be purchased. For details, please see visit the * Orson Charts home page: * * http://www.object-refinery.com/orsoncharts/index.html * */ package org.jfree.chart3d.table; import java.awt.Color; import java.awt.GradientPaint; import java.awt.Graphics2D; import java.awt.Paint; import java.awt.geom.Point2D; import java.awt.geom.Rectangle2D; import java.io.Serializable; import org.jfree.chart3d.TitleAnchor; import org.jfree.chart3d.graphics2d.Anchor2D; import org.jfree.chart3d.internal.Args; import org.jfree.chart3d.internal.ObjectUtils; /** * A {@link RectanglePainter} that can fill a rectangle with a gradient (the * gradient is generated using anchor points to fit any size rectangle on * demand). Instances of this class are immutable. *

* NOTE: This class is serializable, but the serialization format is subject * to change in future releases and should not be relied upon for persisting * instances of this class. */ @SuppressWarnings("serial") public final class GradientRectanglePainter implements RectanglePainter, Serializable { /** The first color for the gradient. */ private final Color color1; /** The anchor point used to find the starting point for the gradient. */ private final Anchor2D anchor1; /** The first color for the gradient. */ private final Color color2; /** The anchor point used to find the ending point for the gradient. */ private final Anchor2D anchor2; /** * Creates a new instance. *

* NOTE: some useful standard anchor points are defined in the * {@link TitleAnchor} class. * * @param color1 the first color for the gradient ({@code null} not * permitted). * @param anchor1 the anchor point used to determine the starting point * for the gradient ({@code null} not permitted). * @param color2 the second color for the gradient ({@code null} not * permitted). * @param anchor2 the anchor point used to determine the ending point for * the gradient ({@code null} not permitted). */ public GradientRectanglePainter(Color color1, Anchor2D anchor1, Color color2, Anchor2D anchor2) { Args.nullNotPermitted(color1, "color1"); Args.nullNotPermitted(anchor1, "anchor1"); Args.nullNotPermitted(color2, "color2"); Args.nullNotPermitted(anchor2, "anchor2"); this.color1 = color1; this.anchor1 = anchor1; this.color2 = color2; this.anchor2 = anchor2; } /** * Returns the first color for the gradient (as specified via the * constructor). There is no setter method because instances of this class * are immutable. * * @return The first color for the gradient (never {@code null}). */ public Color getColor1() { return this.color1; } /** * Returns the anchor point used to find the starting point for the * gradient (as specified via the constructor). There is no setter method * because instances of this class are immutable. * * @return The anchor point (never {@code null}). */ public Anchor2D getAnchor1() { return this.anchor1; } /** * Returns the second color for the gradient (as specified via the * constructor). There is no setter method because instances of this class * are immutable. * * @return The second color for the gradient (never {@code null}). */ public Color getColor2() { return this.color2; } /** * Returns the anchor point used to find the ending point for the * gradient (as specified via the constructor). There is no setter method * because instances of this class are immutable. * * @return The anchor point (never {@code null}). */ public Anchor2D getAnchor2() { return this.anchor2; } /** * Returns a {@code GradientPaint} instance with coordinates based * on the painter's anchor points and the supplied rectangle. * * @param area the area ({@code null} not permitted). * * @return A gradient paint (never {@code null}). */ private GradientPaint createTransformedGradient(Rectangle2D area) { // defer arg check Point2D pt1 = this.anchor1.getAnchorPoint(area); Point2D pt2 = this.anchor2.getAnchorPoint(area); return new GradientPaint(pt1, this.color1, pt2, this.color2); } /** * Fills the specified {@code area} with a gradient paint created * using the colors and anchor points of this painter. * * @param g2 the graphics target ({@code null} not permitted). * @param area the area to fill ({@code null} not permitted). */ @Override public void fill(Graphics2D g2, Rectangle2D area) { Paint saved = g2.getPaint(); g2.setPaint(createTransformedGradient(area)); g2.fill(area); g2.setPaint(saved); } /** * Tests this instance for equality with an arbitrary object. * * @param obj the object ({@code null} not permitted). * * @return A boolean. */ @Override public boolean equals(Object obj) { if (obj == this) { return true; } if (!(obj instanceof GradientRectanglePainter)) { return false; } GradientRectanglePainter that = (GradientRectanglePainter) obj; if (!this.color1.equals(that.color1)) { return false; } if (!this.anchor1.equals(that.anchor1)) { return false; } if (!this.color2.equals(that.color2)) { return false; } if (!this.anchor2.equals(that.anchor2)) { return false; } return true; } @Override public int hashCode() { int hash = 5; hash = 67 * hash + ObjectUtils.hashCode(this.color1); hash = 67 * hash + ObjectUtils.hashCode(this.anchor1); hash = 67 * hash + ObjectUtils.hashCode(this.color2); hash = 67 * hash + ObjectUtils.hashCode(this.anchor2); return hash; } } orson-charts-2.1.0/src/main/java/org/jfree/chart3d/table/GridElement.java000066400000000000000000000233171417331271500261450ustar00rootroot00000000000000/* =========================================================== * Orson Charts : a 3D chart library for the Java(tm) platform * =========================================================== * * (C)opyright 2013-2022, by David Gilbert. All rights reserved. * * https://github.com/jfree/orson-charts * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . * * [Oracle and Java are registered trademarks of Oracle and/or its affiliates. * Other names may be trademarks of their respective owners.] * * If you do not wish to be bound by the terms of the GPL, an alternative * commercial license can be purchased. For details, please see visit the * Orson Charts home page: * * http://www.object-refinery.com/orsoncharts/index.html * */ package org.jfree.chart3d.table; import java.awt.Color; import java.awt.Dimension; import java.awt.Graphics2D; import java.awt.geom.Dimension2D; import java.awt.geom.Rectangle2D; import java.io.Serializable; import java.util.Map; import java.util.ArrayList; import java.util.List; import java.awt.Insets; import org.jfree.chart3d.data.DefaultKeyedValues2D; /** * A table element that contains a grid of elements. *

* NOTE: This class is serializable, but the serialization format is subject * to change in future releases and should not be relied upon for persisting * instances of this class. */ @SuppressWarnings("serial") public class GridElement, C extends Comparable> extends AbstractTableElement implements TableElement, Serializable { private static final Color TRANSPARENT_COLOR = new Color(0, 0, 0, 0); /** Storage for the cell elements. */ private DefaultKeyedValues2D elements; /** * Creates a new empty grid. */ public GridElement() { this.elements = new DefaultKeyedValues2D<>(); setBackgroundColor(TRANSPARENT_COLOR); } /** * Adds (or updates) a cell in the grid. * * @param element the element ({@code null} permitted). * @param rowKey the row key ({@code null} not permitted). * @param columnKey the column key ({@code null} not permitted). */ public void setElement(TableElement element, R rowKey, C columnKey) { // defer argument checking this.elements.setValue(element, rowKey, columnKey); } /** * Receives a visitor by calling the visitor's {@code visit()} method * for each of the children in the grid, and finally for the grid itself. * * @param visitor the visitor ({@code null} not permitted). * * @since 1.2 */ @Override public void receive(TableElementVisitor visitor) { for (int r = 0; r < this.elements.getRowCount(); r++) { for (int c = 0; c < this.elements.getColumnCount(); c++) { TableElement element = this.elements.getValue(r, c); if (element != null) { element.receive(visitor); } } } visitor.visit(this); } /** * Finds the cell dimensions. * * @param g2 the graphics target (required to calculate font sizes). * @param bounds the bounds. * * @return The cell dimensions (result[0] is the widths, result[1] is the * heights). */ private double[][] findCellDimensions(Graphics2D g2, Rectangle2D bounds) { int rowCount = this.elements.getRowCount(); int columnCount = this.elements.getColumnCount(); double[] widths = new double[columnCount]; double[] heights = new double[rowCount]; // calculate the maximum width for each column for (int r = 0; r < elements.getRowCount(); r++) { for (int c = 0; c < this.elements.getColumnCount(); c++) { TableElement element = this.elements.getValue(r, c); if (element == null) { continue; } Dimension2D dim = element.preferredSize(g2, bounds); widths[c] = Math.max(widths[c], dim.getWidth()); heights[r] = Math.max(heights[r], dim.getHeight()); } } return new double[][] { widths, heights }; } /** * Returns the preferred size of the element (including insets). * * @param g2 the graphics target. * @param bounds the bounds. * @param constraints the constraints (ignored for now). * * @return The preferred size. */ @Override public Dimension2D preferredSize(Graphics2D g2, Rectangle2D bounds, Map constraints) { Insets insets = getInsets(); double[][] cellDimensions = findCellDimensions(g2, bounds); double[] widths = cellDimensions[0]; double[] heights = cellDimensions[1]; double w = insets.left + insets.right; for (int i = 0; i < widths.length; i++) { w = w + widths[i]; } double h = insets.top + insets.bottom; for (int i = 0; i < heights.length; i++) { h = h + heights[i]; } return new Dimension((int) w, (int) h); } /** * Performs a layout of this table element, returning a list of bounding * rectangles for the element and its subelements. * * @param g2 the graphics target. * @param bounds the bounds. * @param constraints the constraints (if any). * * @return A list of bounding rectangles. */ @Override public List layoutElements(Graphics2D g2, Rectangle2D bounds, Map constraints) { double[][] cellDimensions = findCellDimensions(g2, bounds); double[] widths = cellDimensions[0]; double[] heights = cellDimensions[1]; List result = new ArrayList<>( this.elements.getRowCount() * this.elements.getColumnCount()); double y = bounds.getY() + getInsets().top; for (int r = 0; r < elements.getRowCount(); r++) { double x = bounds.getX() + getInsets().left; for (int c = 0; c < this.elements.getColumnCount(); c++) { Rectangle2D cellBounds = new Rectangle2D.Double(x, y, widths[c], heights[r]); TableElement element = this.elements.getValue(r, c); element.layoutElements(g2, cellBounds, null); result.add(cellBounds); x += widths[c]; } y = y + heights[r]; } return result; } /** * Draws the element within the specified bounds. * * @param g2 the graphics target. * @param bounds the bounds. */ @Override public void draw(Graphics2D g2, Rectangle2D bounds) { draw(g2, bounds, null); } /** * Draws the element within the specified bounds. If the * {@code recordBounds} flag is set, this element and each of its * children will have their {@code BOUNDS_2D} property updated with * the current bounds. * * @param g2 the graphics target ({@code null} not permitted). * @param bounds the bounds ({@code null} not permitted). * @param onDrawHandler an object that will receive notification before * and after the element is drawn ({@code null} permitted). * * @since 1.3 */ @Override public void draw(Graphics2D g2, Rectangle2D bounds, TableElementOnDraw onDrawHandler) { if (onDrawHandler != null) { onDrawHandler.beforeDraw(this, g2, bounds); } if (getBackground() != null) { getBackground().fill(g2, bounds); } List positions = layoutElements(g2, bounds, null); for (int r = 0; r < this.elements.getRowCount(); r++) { for (int c = 0; c < this.elements.getColumnCount(); c++) { TableElement element = this.elements.getValue(r, c); if (element == null) { continue; } Rectangle2D pos = positions.get(r * elements.getColumnCount() + c); element.draw(g2, pos, onDrawHandler); } } if (onDrawHandler != null) { onDrawHandler.afterDraw(this, g2, bounds); } } /** * Tests this element for equality with an arbitrary object. * * @param obj the object ({@code null} permitted). * * @return A boolean. */ @Override public boolean equals(Object obj) { if (obj == this) { return true; } if (!(obj instanceof GridElement)) { return false; } GridElement that = (GridElement) obj; if (!this.elements.equals(that.elements)) { return false; } return true; } /** * Returns a string representation of this element, primarily for * debugging purposes. * * @return A string representation of this element. */ @Override public String toString() { return "GridElement[rowCount=" + this.elements.getRowCount() + ", columnCount=" + this.elements.getColumnCount() + "]"; } } orson-charts-2.1.0/src/main/java/org/jfree/chart3d/table/HAlign.java000066400000000000000000000030551417331271500251050ustar00rootroot00000000000000/* =========================================================== * Orson Charts : a 3D chart library for the Java(tm) platform * =========================================================== * * (C)opyright 2013-2022, by David Gilbert. All rights reserved. * * https://github.com/jfree/orson-charts * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . * * [Oracle and Java are registered trademarks of Oracle and/or its affiliates. * Other names may be trademarks of their respective owners.] * * If you do not wish to be bound by the terms of the GPL, an alternative * commercial license can be purchased. For details, please see visit the * Orson Charts home page: * * http://www.object-refinery.com/orsoncharts/index.html * */ package org.jfree.chart3d.table; /** * Horizontal alignment options. */ public enum HAlign { /** Left alignment. */ LEFT, /** Center alignment. */ CENTER, /** Right alignment. */ RIGHT } orson-charts-2.1.0/src/main/java/org/jfree/chart3d/table/RectanglePainter.java000066400000000000000000000045031417331271500271710ustar00rootroot00000000000000/* =========================================================== * Orson Charts : a 3D chart library for the Java(tm) platform * =========================================================== * * (C)opyright 2013-2022, by David Gilbert. All rights reserved. * * https://github.com/jfree/orson-charts * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . * * [Oracle and Java are registered trademarks of Oracle and/or its affiliates. * Other names may be trademarks of their respective owners.] * * If you do not wish to be bound by the terms of the GPL, an alternative * commercial license can be purchased. For details, please see visit the * Orson Charts home page: * * http://www.object-refinery.com/orsoncharts/index.html * */ package org.jfree.chart3d.table; import java.awt.Graphics2D; import java.awt.geom.Rectangle2D; import org.jfree.chart3d.Chart3D; /** * An object that can paint a rectangular region with a color, gradient, image * or anything. *

* NOTE: It is recommended that classes that implement this interface are * designed to be {@code Serializable} and immutable. Immutability is * desirable because painters are assigned to {@link Chart3D} instances, and * there is no change notification if the painter can be modified directly. * In addition, a single painter can be shared amongst multiple charts. */ public interface RectanglePainter { /** * Fills the specified rectangle (where "fill" is some arbitrary drawing * operation defined by the class that implements this interface). * * @param g2 the graphics target ({@code null} not permitted). * @param bounds the rectangle ({@code null} not permitted). */ void fill(Graphics2D g2, Rectangle2D bounds); } orson-charts-2.1.0/src/main/java/org/jfree/chart3d/table/ShapeElement.java000066400000000000000000000145111417331271500263140ustar00rootroot00000000000000/* =========================================================== * Orson Charts : a 3D chart library for the Java(tm) platform * =========================================================== * * (C)opyright 2013-2022, by David Gilbert. All rights reserved. * * https://github.com/jfree/orson-charts * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . * * [Oracle and Java are registered trademarks of Oracle and/or its affiliates. * Other names may be trademarks of their respective owners.] * * If you do not wish to be bound by the terms of the GPL, an alternative * commercial license can be purchased. For details, please see visit the * Orson Charts home page: * * http://www.object-refinery.com/orsoncharts/index.html * */ package org.jfree.chart3d.table; import java.awt.Color; import java.awt.Graphics2D; import java.awt.Insets; import java.awt.Shape; import java.awt.geom.AffineTransform; import java.awt.geom.Dimension2D; import java.awt.geom.Rectangle2D; import java.util.ArrayList; import java.util.List; import java.util.Map; import org.jfree.chart3d.internal.Args; /** * A table element that displays a shape. *

* NOTE: This class is serializable, but the serialization format is subject * to change in future releases and should not be relied upon for persisting * instances of this class. */ @SuppressWarnings("serial") public class ShapeElement extends AbstractTableElement implements TableElement { /** * The shape (by convention, the shape should be centered on the point * (0, 0)). */ private final Shape shape; private Color fillColor; /** * Creates a new shape element. * * @param shape the shape ({@code null} not permitted). * @param fillColor the fill color ({@code null} not permitted). */ public ShapeElement(Shape shape, Color fillColor) { super(); Args.nullNotPermitted(shape, "shape"); Args.nullNotPermitted(fillColor, "fillColor"); this.shape = shape; this.fillColor = fillColor; } /** * Returns the fill color. * * @return The fill color. * * @since 1.2 */ public Color getFillColor() { return this.fillColor; } /** * Sets the fill color. * * @param color the fill color ({@code null} not permitted). * * @since 1.2 */ public void setFillColor(Color color) { Args.nullNotPermitted(color, "color"); this.fillColor = color; } @Override public Dimension2D preferredSize(Graphics2D g2, Rectangle2D bounds, Map constraints) { Insets insets = getInsets(); Rectangle2D shapeBounds = shape.getBounds2D(); return new ElementDimension(Math.min(shapeBounds.getWidth() + insets.left + insets.right, bounds.getWidth()), Math.min(shapeBounds.getHeight() + insets.top + insets.bottom, bounds.getHeight())); } @Override public List layoutElements(Graphics2D g2, Rectangle2D bounds, Map constraints) { List result = new ArrayList<>(1); Insets insets = getInsets(); Rectangle2D shapeBounds = this.shape.getBounds2D(); double w = Math.min(shapeBounds.getWidth() + insets.left + insets.right, bounds.getWidth()); double h = Math.min(shapeBounds.getHeight() + insets.top + insets.bottom, bounds.getHeight()); Rectangle2D pos = new Rectangle2D.Double(bounds.getCenterX() - w / 2.0, bounds.getCenterY() - h / 2.0, w, h); result.add(pos); return result; } /** * Draws the shape element within the specified bounds. * * @param g2 the graphics target ({@code null} not permitted). * @param bounds the bounds ({@code null} not permitted). */ @Override public void draw(Graphics2D g2, Rectangle2D bounds) { draw(g2, bounds, null); } /** * Draws the element within the specified bounds. If the * {@code recordBounds} flag is set, this element and each of its * children will have their {@code BOUNDS_2D} property updated with * the current bounds. * * @param g2 the graphics target ({@code null} not permitted). * @param bounds the bounds ({@code null} not permitted). * @param onDrawHandler an object that will receive notification before * and after the element is drawn ({@code null} permitted). * * @since 1.3 */ @Override public void draw(Graphics2D g2, Rectangle2D bounds, TableElementOnDraw onDrawHandler) { if (onDrawHandler != null) { onDrawHandler.beforeDraw(this, g2, bounds); } AffineTransform saved = g2.getTransform(); RectanglePainter background = getBackground(); if (background != null) { background.fill(g2, bounds); } g2.translate(bounds.getCenterX(), bounds.getCenterY()); g2.setPaint(this.fillColor); g2.fill(shape); g2.setTransform(saved); if (onDrawHandler != null) { onDrawHandler.afterDraw(this, g2, bounds); } } /** * Receives a visitor. * * @param visitor the visitor ({@code null} not permitted). * * @since 1.2 */ @Override public void receive(TableElementVisitor visitor) { visitor.visit(this); } /** * Returns a string representation of this element, primarily for * debugging purposes. * * @return A string representation of this element. */ @Override public String toString() { return "ShapeElement[shape=" + this.shape + "]"; } } orson-charts-2.1.0/src/main/java/org/jfree/chart3d/table/StandardRectanglePainter.java000066400000000000000000000147231417331271500306570ustar00rootroot00000000000000/* =========================================================== * Orson Charts : a 3D chart library for the Java(tm) platform * =========================================================== * * (C)opyright 2013-2022, by David Gilbert. All rights reserved. * * https://github.com/jfree/orson-charts * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . * * [Oracle and Java are registered trademarks of Oracle and/or its affiliates. * Other names may be trademarks of their respective owners.] * * If you do not wish to be bound by the terms of the GPL, an alternative * commercial license can be purchased. For details, please see visit the * Orson Charts home page: * * http://www.object-refinery.com/orsoncharts/index.html * */ package org.jfree.chart3d.table; import java.awt.Dimension; import java.awt.Image; import java.awt.Graphics2D; import java.awt.Paint; import java.awt.geom.Rectangle2D; import java.io.Serializable; import java.io.IOException; import java.io.ObjectInputStream; import java.io.ObjectOutputStream; import org.jfree.chart3d.graphics2d.Anchor2D; import org.jfree.chart3d.graphics2d.Fit2D; import org.jfree.chart3d.graphics2d.Scale2D; import org.jfree.chart3d.internal.Args; import org.jfree.chart3d.internal.ObjectUtils; import org.jfree.chart3d.internal.SerialUtils; /** * A {@link RectanglePainter} that fills the rectangle with a * color or image. Instances of this class are immutable. *

* Note that it is possible to use gradient paint with this painter, but it is * usually better to use {@link GradientRectanglePainter} since it provides * options to transform the gradient to fit the chart background size. *

* NOTE: This class is serializable, but the serialization format is subject * to change in future releases and should not be relied upon for persisting * instances of this class. */ @SuppressWarnings("serial") public class StandardRectanglePainter implements RectanglePainter, Serializable { /** The paint (never {@code null}). */ private transient Paint paint; /** A background image for the chart, if any. */ private transient Image image; private Fit2D imageFit; /** * Creates a new painter that will fill a rectangle with the specified * paint. * * @param paint the fill paint ({@code null} not permitted). */ public StandardRectanglePainter(Paint paint) { this(paint, null, null); } /** * Creates a new painter that will draw an image within the specified * rectangle. * * @param paint the background paint ({@code null} not permitted). * @param image the image ({@code null} permitted). * @param imageFit the fit ({@code null} permitted). */ public StandardRectanglePainter(Paint paint, Image image, Fit2D imageFit) { Args.nullNotPermitted(paint, "paint"); this.paint = paint; this.image = image; this.imageFit = new Fit2D(Anchor2D.TOP_CENTER, Scale2D.SCALE_BOTH); if (imageFit != null) { this.imageFit = imageFit; } } /** * Returns the paint that will be used to fill rectangles. * * @return The paint (never {@code null}). */ public Paint getPaint() { return this.paint; } /** * Returns the image. * * @return The image (possibly {@code null}). */ public Image getImage() { return this.image; } /** * Returns the image fit specification. * * @return The image fit specification. */ public Fit2D getImageFit() { return this.imageFit; } /** * Fills the rectangle with the paint specified in the constructor. * * @param g2 the graphics target ({@code null} not permitted). * @param bounds the rectangle ({@code null} not permitted). */ @Override public void fill(Graphics2D g2, Rectangle2D bounds) { Paint saved = g2.getPaint(); g2.setPaint(this.paint); g2.fill(bounds); if (this.image != null) { int w = this.image.getWidth(null); int h = this.image.getHeight(null); Rectangle2D imageBounds = this.imageFit.fit(new Dimension(w, h), bounds); g2.drawImage(this.image, (int) imageBounds.getX(), (int) imageBounds.getY(), (int) imageBounds.getWidth(), (int) imageBounds.getHeight(), null); } g2.setPaint(saved); } /** * Tests this painter for equality with an arbitrary object. * * @param obj the object ({@code null} permitted). * * @return A boolean. */ @Override public boolean equals(Object obj) { if (obj == this) { return true; } if (!(obj instanceof StandardRectanglePainter)) { return false; } StandardRectanglePainter that = (StandardRectanglePainter) obj; if (!ObjectUtils.equalsPaint(this.paint, that.paint)) { return false; } return true; } /** * Provides serialization support. * * @param stream the output stream. * * @throws IOException if there is an I/O error. */ private void writeObject(ObjectOutputStream stream) throws IOException { stream.defaultWriteObject(); SerialUtils.writePaint(this.paint, stream); // TODO : serialize the image } /** * Provides serialization support. * * @param stream the input stream. * * @throws IOException if there is an I/O error. * @throws ClassNotFoundException if there is a classpath problem. */ private void readObject(ObjectInputStream stream) throws IOException, ClassNotFoundException { stream.defaultReadObject(); this.paint = SerialUtils.readPaint(stream); // deserialize the image } } orson-charts-2.1.0/src/main/java/org/jfree/chart3d/table/TableElement.java000066400000000000000000000141541417331271500263060ustar00rootroot00000000000000/* =========================================================== * Orson Charts : a 3D chart library for the Java(tm) platform * =========================================================== * * (C)opyright 2013-2022, by David Gilbert. All rights reserved. * * https://github.com/jfree/orson-charts * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . * * [Oracle and Java are registered trademarks of Oracle and/or its affiliates. * Other names may be trademarks of their respective owners.] * * If you do not wish to be bound by the terms of the GPL, an alternative * commercial license can be purchased. For details, please see visit the * Orson Charts home page: * * http://www.object-refinery.com/orsoncharts/index.html * */ package org.jfree.chart3d.table; import java.awt.Graphics2D; import java.awt.geom.Dimension2D; import java.awt.geom.Rectangle2D; import java.util.List; import java.util.Map; import org.jfree.chart3d.graphics2d.RefPt2D; /** * An element (typically a single cell) in a table. This interface defines * methods for determining the preferred size of the element, for laying out * the element (including sub-elements if there are any), and drawing the * element within specified bounds. Various kinds of table elements will be * used to construct interesting tables. *

* It is important that these methods are implemented in a stateless manner. * There is some redundancy in calculation between the layout and drawing * methods in order to preserve the statelessness, but it is important to * ensure that table elements can be rendered to multiple targets * simultaneously. * */ public interface TableElement { /** * A property key for the class of a table element. * * @since 1.3 */ String CLASS = "class"; /** * Calculates the preferred size for the element, with reference to the * specified bounds. The preferred size can exceed the bounds, but the * bounds might influence how sub-elements are sized and/or positioned. * For example, in a {@link FlowElement}, the width of the bounds will * determine when the flow layout wraps. * * @param g2 the graphics target ({@code null} not permitted). * @param bounds the bounds ({@code null} not permitted). * * @return The preferred size (never {@code null}). */ Dimension2D preferredSize(Graphics2D g2, Rectangle2D bounds); /** * Returns the preferred size of the element, subject to the supplied * constraints. * * @param g2 the graphics target ({@code null} not permitted). * @param bounds the bounds ({@code null} not permitted). * @param constraints the constraints ({@code null} permitted). * * @return The preferred size. */ Dimension2D preferredSize(Graphics2D g2, Rectangle2D bounds, Map constraints); /** * Returns the reference point used to align the element with the bounding * rectangle within which it is drawn. * * @return The anchor point (never {@code null}). */ RefPt2D getRefPoint(); /** * Performs a layout of this table element, returning a list of bounding * rectangles for the element and its subelements. This method is * typically called by the {@link #draw(java.awt.Graphics2D, * java.awt.geom.Rectangle2D)} method. * * @param g2 the graphics target ({@code null} not permitted). * @param bounds the bounds ({@code null} not permitted). * @param constraints the constraints (if any). * * @return A list of bounding rectangles. */ List layoutElements(Graphics2D g2, Rectangle2D bounds, Map constraints); /** * Draws the element within the specified bounds. * * @param g2 the graphics target ({@code null} not permitted). * @param bounds the bounds ({@code null} not permitted). */ void draw(Graphics2D g2, Rectangle2D bounds); /** * Draws the element within the specified bounds. The * {@code onDrawHandler} provides (optional) access to all elements * before and after they are rendered. * * @param g2 the graphics target ({@code null} not permitted). * @param bounds the bounds ({@code null} not permitted). * @param onDrawHandler an object that will receive notification before * and after the element is drawn ({@code null} permitted). * * @since 1.3 */ void draw(Graphics2D g2, Rectangle2D bounds, TableElementOnDraw onDrawHandler); /** * Returns the value of the property with the specified key, or * {@code null}. * * @param key the key ({@code null} not permitted). * * @return The property value or {@code null}. * * @since 1.3 */ Object getProperty(String key); /** * Sets the value of the property with the specified key. * * @param key the key ({@code null} not permitted). * @param value the value ({@code null} permitted). * * @since 1.3 */ void setProperty(String key, Object value); /** * Receives a {@link TableElementVisitor}. The visitor will have its * {@code visit(TableElement)} method called for each child element * of this table element (if it has children) and then for this element. * * @param visitor the visitor ({@code null} not permitted). * * @since 1.2 */ void receive(TableElementVisitor visitor); } orson-charts-2.1.0/src/main/java/org/jfree/chart3d/table/TableElementOnDraw.java000066400000000000000000000044521417331271500274210ustar00rootroot00000000000000/* =========================================================== * Orson Charts : a 3D chart library for the Java(tm) platform * =========================================================== * * (C)opyright 2013-2022, by David Gilbert. All rights reserved. * * https://github.com/jfree/orson-charts * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . * * [Oracle and Java are registered trademarks of Oracle and/or its affiliates. * Other names may be trademarks of their respective owners.] * * If you do not wish to be bound by the terms of the GPL, an alternative * commercial license can be purchased. For details, please see visit the * Orson Charts home page: * * http://www.object-refinery.com/orsoncharts/index.html * */ package org.jfree.chart3d.table; import java.awt.Graphics2D; import java.awt.geom.Rectangle2D; /** * An interface that provides access to the {@link TableElement} rendering * process. * * @since 1.3 */ public interface TableElementOnDraw { /** * A callback method that is called before an element is drawn. * * @param element the element ({@code null} not permitted). * @param g2 the graphics target ({@code null} not permitted). * @param bounds the bounds ({@code null} not permitted). */ void beforeDraw(TableElement element, Graphics2D g2, Rectangle2D bounds); /** * A callback method that is called after an element is drawn. * * @param element the element ({@code null} not permitted). * @param g2 the graphics target ({@code null} not permitted). * @param bounds the bounds ({@code null} not permitted). */ void afterDraw(TableElement element, Graphics2D g2, Rectangle2D bounds); } orson-charts-2.1.0/src/main/java/org/jfree/chart3d/table/TableElementStyler.java000066400000000000000000000060101417331271500275010ustar00rootroot00000000000000/* =========================================================== * Orson Charts : a 3D chart library for the Java(tm) platform * =========================================================== * * (C)opyright 2013-2022, by David Gilbert. All rights reserved. * * https://github.com/jfree/orson-charts * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . * * [Oracle and Java are registered trademarks of Oracle and/or its affiliates. * Other names may be trademarks of their respective owners.] * * If you do not wish to be bound by the terms of the GPL, an alternative * commercial license can be purchased. For details, please see visit the * Orson Charts home page: * * http://www.object-refinery.com/orsoncharts/index.html * */ package org.jfree.chart3d.table; import java.awt.Color; import java.awt.Font; import java.util.HashMap; import java.util.Map; /** * A table element visitor that applies style changes. * * @since 1.2 */ public class TableElementStyler implements TableElementVisitor { private final Map fontChanges; private final Map foregroundColorChanges; private final Map backgroundColorChanges; /** * Creates a new styler. The keys in each map are tag values - each * element with a matching tag will have the associated value applied * to it. * * @param fontChanges a map of font changes. * @param fgChanges a map of foreground color changes. * @param bgChanges a map of background color changes. */ public TableElementStyler(Map fontChanges, Map fgChanges, Map bgChanges) { this.fontChanges = new HashMap<>(fontChanges); this.foregroundColorChanges = fgChanges; this.backgroundColorChanges = bgChanges; } @Override public void visit(TableElement element) { if (element instanceof TextElement) { TextElement te = (TextElement) element; Font f = this.fontChanges.get(te.getTag()); if (f != null) { te.setFont(f); } Color bg = this.backgroundColorChanges.get(te.getTag()); if (bg != null) { te.setBackgroundColor(bg); } Color fg = this.foregroundColorChanges.get(te.getTag()); if (fg != null) { te.setColor(fg); } } } } orson-charts-2.1.0/src/main/java/org/jfree/chart3d/table/TableElementVisitor.java000066400000000000000000000033421417331271500276630ustar00rootroot00000000000000/* =========================================================== * Orson Charts : a 3D chart library for the Java(tm) platform * =========================================================== * * (C)opyright 2013-2022, by David Gilbert. All rights reserved. * * https://github.com/jfree/orson-charts * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . * * [Oracle and Java are registered trademarks of Oracle and/or its affiliates. * Other names may be trademarks of their respective owners.] * * If you do not wish to be bound by the terms of the GPL, an alternative * commercial license can be purchased. For details, please see visit the * Orson Charts home page: * * http://www.object-refinery.com/orsoncharts/index.html * */ package org.jfree.chart3d.table; /** * A table element visitor. This is a general purpose mechanism to traverse * a hierarchy of table elements. * * @since 1.2 */ public interface TableElementVisitor { /** * Performs the visitor's operation on the table element. * * @param element the element ({@code null} not permitted). */ void visit(TableElement element); } orson-charts-2.1.0/src/main/java/org/jfree/chart3d/table/TextElement.java000066400000000000000000000240411417331271500261770ustar00rootroot00000000000000/* =========================================================== * Orson Charts : a 3D chart library for the Java(tm) platform * =========================================================== * * (C)opyright 2013-2022, by David Gilbert. All rights reserved. * * https://github.com/jfree/orson-charts * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . * * [Oracle and Java are registered trademarks of Oracle and/or its affiliates. * Other names may be trademarks of their respective owners.] * * If you do not wish to be bound by the terms of the GPL, an alternative * commercial license can be purchased. For details, please see visit the * Orson Charts home page: * * http://www.object-refinery.com/orsoncharts/index.html * */ package org.jfree.chart3d.table; import java.awt.Color; import java.awt.Font; import java.awt.Graphics2D; import java.awt.Insets; import java.awt.geom.Dimension2D; import java.awt.geom.Rectangle2D; import java.io.Serializable; import java.util.ArrayList; import java.util.List; import java.util.Map; import org.jfree.chart3d.graphics2d.TextAnchor; import org.jfree.chart3d.internal.Args; import org.jfree.chart3d.internal.TextUtils; /** * A table element consisting of some text that will be drawn on one line. *

* NOTE: This class is serializable, but the serialization format is subject * to change in future releases and should not be relied upon for persisting * instances of this class. */ @SuppressWarnings("serial") public class TextElement extends AbstractTableElement implements TableElement, Serializable { /** * The default font. * * @since 1.1 */ public static final Font DEFAULT_FONT = new Font("Dialog", Font.PLAIN, 12); /** The text (never {@code null}). */ private String text; /** The font (never {@code null}). */ private Font font; /** The color for the text (never {@code null}). */ private Color color; /** The horizontal alignment (never {@code null}). */ private HAlign alignment; /** * Creates a new element that will display the specified text using the * default font ({@link #DEFAULT_FONT}). * * @param text the text ({@code null} not permitted). */ public TextElement(String text) { this(text, DEFAULT_FONT); } /** * Creates a new instance. * * @param text the text ({@code null} not permitted). * @param font the font ({@code null} not permitted). */ public TextElement(String text, Font font) { super(); Args.nullNotPermitted(text, "text"); Args.nullNotPermitted(font, "font"); this.text = text; this.font = font; this.color = Color.BLACK; this.alignment = HAlign.LEFT; } /** * Returns the font. The default value is {@link #DEFAULT_FONT}. * * @return The font (never {@code null}). */ public Font getFont() { return this.font; } /** * Sets the font. * * @param font the font ({@code null} not permitted). */ public void setFont(Font font) { Args.nullNotPermitted(font, "font"); this.font = font; } /** * Returns the foreground color for the text element. The default value * is {@code Color#BLACK}. * * @return The foreground color (never {@code null}). */ public Color getColor() { return this.color; } /** * Sets the foreground color for the text element. * * @param color the new color ({@code null} not permitted). */ public void setColor(Color color) { Args.nullNotPermitted(color, "color"); this.color = color; } /** * Returns the horizontal alignment that will be used when rendering the * text. The default value is {@code LEFT}. * * @return The horizontal alignment (never {@code null}). */ public HAlign getHorizontalAlignment() { return this.alignment; } /** * Sets the horizontal alignment. * * @param align the alignment ({@code null} not permitted). */ public void setHorizontalAligment(HAlign align) { Args.nullNotPermitted(align, "align"); this.alignment = align; } /** * Returns the preferred size of the element (including insets). * * @param g2 the graphics target. * @param bounds the bounds. * @param constraints the constraints (ignored for now). * * @return The preferred size. */ @Override public Dimension2D preferredSize(Graphics2D g2, Rectangle2D bounds, Map constraints) { g2.setFont(this.font); Rectangle2D textBounds = TextUtils.getTextBounds(this.text, g2.getFontMetrics(this.font)); Insets insets = getInsets(); double w = Math.min(textBounds.getWidth() + insets.left + insets.right, bounds.getWidth()); double h = Math.min(textBounds.getHeight() + insets.top + insets.bottom, bounds.getHeight()); return new ElementDimension(w, h); } /** * Performs a layout of this table element, returning a list of bounding * rectangles for the element and its subelements. * * @param g2 the graphics target. * @param bounds the bounds. * @param constraints the constraints (if any). * * @return A list containing the bounding rectangle for the text (as the * only item in the list). */ @Override public List layoutElements(Graphics2D g2, Rectangle2D bounds, Map constraints) { g2.setFont(this.font); Rectangle2D textBounds = TextUtils.getTextBounds(this.text, g2.getFontMetrics(this.font)); Insets insets = getInsets(); double width = textBounds.getWidth() + insets.left + insets.right; double x = bounds.getX(); switch (this.alignment) { case LEFT: x = bounds.getX(); break; case CENTER: x = bounds.getCenterX() - width / 2.0 - insets.left; break; case RIGHT: x = bounds.getMaxX() - width - insets.right; break; default: throw new IllegalStateException("HAlign: " + this.alignment); } double y = bounds.getY(); double w = Math.min(width, bounds.getWidth()); double h = Math.min(textBounds.getHeight() + insets.top + insets.bottom, bounds.getHeight()); List result = new ArrayList<>(1); result.add(new Rectangle2D.Double(x, y, w, h)); return result; } /** * Receives a visitor. * * @param visitor the visitor ({@code null} not permitted). * * @since 1.2 */ @Override public void receive(TableElementVisitor visitor) { visitor.visit(this); } /** * Draws the element within the specified bounds. * * @param g2 the graphics target. * @param bounds the bounds. */ @Override public void draw(Graphics2D g2, Rectangle2D bounds) { draw(g2, bounds, null); } /** * Draws the element within the specified bounds. If the * {@code recordBounds} flag is set, this element and each of its * children will have their {@code BOUNDS_2D} property updated with * the current bounds. * * @param g2 the graphics target ({@code null} not permitted). * @param bounds the bounds ({@code null} not permitted). * @param onDrawHandler an object that will receive notification before * and after the element is drawn ({@code null} permitted). */ @Override public void draw(Graphics2D g2, Rectangle2D bounds, TableElementOnDraw onDrawHandler) { if (onDrawHandler != null) { onDrawHandler.beforeDraw(this, g2, bounds); } List layout = layoutElements(g2, bounds, null); Rectangle2D textBounds = layout.get(0); if (getBackground() != null) { getBackground().fill(g2, textBounds); } g2.setPaint(this.color); g2.setFont(this.font); Insets insets = getInsets(); TextUtils.drawAlignedString(this.text, g2, (float) (textBounds.getX() + insets.left), (float) (textBounds.getY() + insets.top), TextAnchor.TOP_LEFT); if (onDrawHandler != null) { onDrawHandler.afterDraw(this, g2, bounds); } } /** * Tests this element for equality with an arbitrary object. * * @param obj the object ({@code null} permitted). * * @return A boolean. */ @Override public boolean equals(Object obj) { if (obj == this) { return true; } if (!(obj instanceof TextElement)) { return false; } TextElement that = (TextElement) obj; if (!this.text.equals(that.text)) { return false; } if (!this.font.equals(that.font)) { return false; } if (!this.color.equals(that.color)) { return false; } if (this.alignment != that.alignment) { return false; } return super.equals(obj); } @Override public String toString() { return "TextElement[text=" + this.text + "]"; } } orson-charts-2.1.0/src/main/java/org/jfree/chart3d/table/VAlign.java000066400000000000000000000030151417331271500251170ustar00rootroot00000000000000/* =========================================================== * Orson Charts : a 3D chart library for the Java(tm) platform * =========================================================== * * (C)opyright 2013-2022, by David Gilbert. All rights reserved. * * https://github.com/jfree/orson-charts * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . * * [Oracle and Java are registered trademarks of Oracle and/or its affiliates. * Other names may be trademarks of their respective owners.] * * If you do not wish to be bound by the terms of the GPL, an alternative * commercial license can be purchased. For details, please see visit the * Orson Charts home page: * * http://www.object-refinery.com/orsoncharts/index.html * */ package org.jfree.chart3d.table; /** * Vertical alignment options. */ public enum VAlign { /** Top. */ TOP, /** Middle. */ MIDDLE, /** Bottom. */ BOTTOM } orson-charts-2.1.0/src/main/java/org/jfree/chart3d/table/VerticalFlowElement.java000066400000000000000000000307231417331271500276600ustar00rootroot00000000000000/* =========================================================== * Orson Charts : a 3D chart library for the Java(tm) platform * =========================================================== * * (C)opyright 2013-2022, by David Gilbert. All rights reserved. * * https://github.com/jfree/orson-charts * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . * * [Oracle and Java are registered trademarks of Oracle and/or its affiliates. * Other names may be trademarks of their respective owners.] * * If you do not wish to be bound by the terms of the GPL, an alternative * commercial license can be purchased. For details, please see visit the * Orson Charts home page: * * http://www.object-refinery.com/orsoncharts/index.html * */ package org.jfree.chart3d.table; import java.awt.Graphics2D; import java.awt.Insets; import java.awt.Shape; import java.awt.geom.Dimension2D; import java.awt.geom.Rectangle2D; import java.io.Serializable; import java.util.ArrayList; import java.util.List; import java.util.Map; import org.jfree.chart3d.graphics2d.Fit2D; import org.jfree.chart3d.internal.Args; /** * A table element that displays a list of sub-elements in a vertical flow * layout. *

* NOTE: This class is serializable, but the serialization format is subject * to change in future releases and should not be relied upon for persisting * instances of this class. * * @since 1.1 */ @SuppressWarnings("serial") public class VerticalFlowElement extends AbstractTableElement implements ContainerElement, Serializable { /** The sub-elements in this flow. */ private List elements; /** The vertical alignment of the contents of each column. */ private VAlign verticalAlignment; /** * The vertical gap between elements in the same column, specified in * Java2D units. */ private int vgap; /** * Creates a new instance (equivalent to * {@code new VerticalFlowElement(VAlign.MIDDLE, 2)}). */ public VerticalFlowElement() { this(VAlign.MIDDLE, 2); } /** * Creates a new instance. * * @param alignment the vertical alignment of columns ({@code null} * not permitted). * @param vgap the gap between elements. */ public VerticalFlowElement(VAlign alignment, int vgap) { Args.nullNotPermitted(alignment, null); this.elements = new ArrayList<>(); this.verticalAlignment = alignment; this.vgap = vgap; } /** * Returns the vertical alignment for the elements. * * @return The vertical alignment (never {@code null}). */ public VAlign getVerticalAlignment() { return this.verticalAlignment; } /** * Sets the vertical alignment of elements within columns, * * @param alignment the alignment ({@code null} not permitted). */ public void setVerticalAlignment(VAlign alignment) { Args.nullNotPermitted(alignment, "alignment"); this.verticalAlignment = alignment; } /** * Returns the vertical gap between elements, in Java2D units. * * @return The vertical gap. */ public int getVGap() { return this.vgap; } /** * Sets the vertical gap between elements. * * @param vgap the gap (in Java2D units). */ public void setVGap(int vgap) { this.vgap = vgap; } /** * Returns a (new) list containing the elements in this flow layout. * * @return A list containing the elements (possibly empty, but never * {@code null}). */ public List getElements() { return new ArrayList<>(this.elements); } /** * Adds a sub-element to the list. * * @param element the element ({@code null} not permitted). */ @Override public void addElement(TableElement element) { Args.nullNotPermitted(element, "element"); this.elements.add(element); } /** * Receives a {@link TableElementVisitor} (the visitor will be received * by all the elements in the flow). * * @param visitor the visitor ({@code null} not permitted). * * @since 1.2 */ @Override public void receive(TableElementVisitor visitor) { for (TableElement element : elements) { element.receive(visitor); } } /** * Returns the preferred size for the element. * * @param g2 the graphics target ({@code null} not permitted). * @param bounds the bounds ({@code null} not permitted). * @param constraints the layout constraints (ignored here). * * @return The preferred size (never {@code null}). */ @Override public Dimension2D preferredSize(Graphics2D g2, Rectangle2D bounds, Map constraints) { Insets insets = getInsets(); double width = insets.left + insets.right; double height = insets.top + insets.bottom; double maxColHeight = 0.0; int elementCount = this.elements.size(); int i = 0; while (i < elementCount) { // get one column of elements... List elementsInColumn = columnOfElements(i, g2, bounds); double colWidth = calcColumnWidth(elementsInColumn); double colHeight = calcColumnHeight(elementsInColumn, this.vgap); maxColHeight = Math.max(colHeight, maxColHeight); width += colWidth; i = i + elementsInColumn.size(); } height += maxColHeight; return new ElementDimension(width, height); } /** * Returns info for as many elements as we can fit into one column. * * @param first the index of the first element. * @param g2 the graphics target. * @param bounds the bounds. * * @return A list of elements and dimensions. */ private List columnOfElements(int first, Graphics2D g2, Rectangle2D bounds) { List result = new ArrayList<>(); int index = first; boolean full = false; double h = getInsets().top + getInsets().bottom; while (index < this.elements.size() && !full) { TableElement element = this.elements.get(index); Dimension2D dim = element.preferredSize(g2, bounds); if (h + dim.getHeight() <= bounds.getHeight() || index == first) { result.add(new ElementInfo(element, dim)); h += dim.getHeight() + this.vgap; index++; } else { full = true; } } return result; } /** * Returns the width of the widest element in the list. * * @param elementInfoList element info list * * @return The width. */ private double calcColumnWidth(List elementInfoList) { double result = 0.0; for (ElementInfo elementInfo : elementInfoList) { result = Math.max(result, elementInfo.getDimension().getWidth()); } return result; } /** * Calculates the total height of the elements that will form one column. * * @param elementInfoList the elements in the column. * @param vgap the gap between elements. * * @return The total height. */ private double calcColumnHeight(List elementInfoList, double vgap) { double result = 0.0; for (ElementInfo elementInfo : elementInfoList) { result += elementInfo.getDimension().getHeight(); } int count = elementInfoList.size(); if (count > 1) { result += (count - 1) * vgap; } return result; } @Override public List layoutElements(Graphics2D g2, Rectangle2D bounds, Map constraints) { int elementCount = this.elements.size(); List result = new ArrayList<>(elementCount); int i = 0; double x = bounds.getX() + getInsets().left; double y = bounds.getY() + getInsets().top; while (i < elementCount) { // get one column of elements... List elementsInColumn = columnOfElements(i, g2, bounds); double width = calcColumnWidth(elementsInColumn); double height = calcColumnHeight(elementsInColumn, this.vgap); if (this.verticalAlignment == VAlign.MIDDLE) { y = bounds.getCenterY() - (height / 2.0); } else if (this.verticalAlignment == VAlign.BOTTOM) { y = bounds.getMaxY() - getInsets().bottom - height; } for (ElementInfo elementInfo : elementsInColumn) { Dimension2D dim = elementInfo.getDimension(); Rectangle2D position = new Rectangle2D.Double(x, y, width, dim.getHeight()); result.add(position); y += position.getHeight() + this.vgap; } i = i + elementsInColumn.size(); x += width; y = bounds.getY() + getInsets().top; } return result; } /** * Draws the element and all of its subelements within the specified * bounds. * * @param g2 the graphics target ({@code null} not permitted). * @param bounds the bounds ({@code null} not permitted). */ @Override public void draw(Graphics2D g2, Rectangle2D bounds) { draw(g2, bounds, null); } /** * Draws the element within the specified bounds. If the * {@code recordBounds} flag is set, this element and each of its * children will have its {@code BOUNDS_2D} property updated with * the current bounds. * * @param g2 the graphics target ({@code null} not permitted). * @param bounds the bounds ({@code null} not permitted). * @param onDrawHandler record the bounds? * * @since 1.3 */ @Override public void draw(Graphics2D g2, Rectangle2D bounds, TableElementOnDraw onDrawHandler) { if (onDrawHandler != null) { onDrawHandler.beforeDraw(this, g2, bounds); } Shape savedClip = g2.getClip(); g2.clip(bounds); // find the preferred size of the flow layout Dimension2D prefDim = preferredSize(g2, bounds); // fit a rectangle of this dimension to the bounds according to the // element anchor Fit2D fitter = Fit2D.getNoScalingFitter(getRefPoint()); Rectangle2D dest = fitter.fit(prefDim, bounds); // perform layout within this bounding rectangle List layoutInfo = layoutElements(g2, dest, null); // draw the elements for (int i = 0; i < this.elements.size(); i++) { Rectangle2D rect = layoutInfo.get(i); TableElement element = this.elements.get(i); element.draw(g2, rect, onDrawHandler); } g2.setClip(savedClip); if (onDrawHandler != null) { onDrawHandler.afterDraw(this, g2, bounds); } } /** * Tests this element for equality with an arbitrary object. * * @param obj the object ({@code null} permitted). * * @return A boolean. */ @Override public boolean equals(Object obj) { if (obj == this) { return true; } if (!(obj instanceof VerticalFlowElement)) { return false; } VerticalFlowElement that = (VerticalFlowElement) obj; if (this.vgap != that.vgap) { return false; } if (this.verticalAlignment != that.verticalAlignment) { return false; } if (!this.elements.equals(that.elements)) { return false; } return super.equals(obj); } } orson-charts-2.1.0/src/main/java/org/jfree/chart3d/table/package-info.java000066400000000000000000000004041417331271500262620ustar00rootroot00000000000000/** * Classes and interfaces for constructing tables for display to the user. * This is used for chart legend construction, but the API is intended to be * general purpose and should not contain any chart-specific code. */ package org.jfree.chart3d.table; orson-charts-2.1.0/src/main/java/org/jfree/chart3d/util/000077500000000000000000000000001417331271500227635ustar00rootroot00000000000000orson-charts-2.1.0/src/main/java/org/jfree/chart3d/util/json/000077500000000000000000000000001417331271500237345ustar00rootroot00000000000000orson-charts-2.1.0/src/main/java/org/jfree/chart3d/util/json/JSONArray.java000066400000000000000000000104671417331271500263570ustar00rootroot00000000000000/* ============ * Orson Charts * ============ * * (C)opyright 2013-2022, by David Gilbert. * * https://github.com/jfree/orson-charts * * JSON.simple * ----------- * The code in this file originates from the JSON.simple project by * FangYidong: * * https://code.google.com/p/json-simple/ * * which is licensed under the Apache Software License version 2.0. * * It has been modified locally and repackaged under * org.jfree.chart3d.util.json.* to avoid conflicts with any other version that * may be present on the classpath. * */ package org.jfree.chart3d.util.json; import java.io.IOException; import java.io.Writer; import java.util.ArrayList; import java.util.Iterator; import java.util.List; /** * A JSON array. *

* This class is for internal use by Orson Charts, it is not * part of the supported API and you should not call it directly. If you need * JSON support in your project you should include JSON.simple * (https://code.google.com/p/json-simple/) or some other JSON library directly * in your project. */ public class JSONArray extends ArrayList implements List, JSONAware, JSONStreamAware { private static final long serialVersionUID = 3957988303675231981L; /** * Encode a list into JSON text and write it to out. * If this list is also a {@link JSONStreamAware} or a {@link JSONAware}, * {@code JSONStreamAware} and {@code JSONAware} specific * behaviours will be ignored at this top level. * * @see org.jfree.chart3d.util.json.JSONValue#writeJSONString(Object, Writer) * * @param list the list ({@code null} permitted). * @param out the output writer ({@code null} not permitted). * * @throws IOException if there is an I/O problem. */ public static void writeJSONString(List list, Writer out) throws IOException { if (list == null) { out.write("null"); return; } boolean first = true; Iterator iter = list.iterator(); out.write('['); while (iter.hasNext()) { if (first) { first = false; } else { out.write(','); } Object value = iter.next(); if (value == null) { out.write("null"); continue; } JSONValue.writeJSONString(value, out); } out.write(']'); } /** * Writes this array to the specified output writer. * * @param out the output writer ({@code null} not permitted). * * @throws IOException if there is an I/O problem. */ @Override public void writeJSONString(Writer out) throws IOException { writeJSONString(this, out); } /** * Convert a list to JSON text. The result is a JSON array. * If this list is also a {@link JSONAware}, {@link JSONAware} specific * behaviours will be omitted at this top level. * * @see org.jfree.chart3d.util.json.JSONValue#toJSONString(Object) * * @param list the list ({@code null} permitted). * * @return JSON text, or "null" if list is null. */ public static String toJSONString(List list){ if (list == null) { return "null"; } boolean first = true; StringBuilder sb = new StringBuilder(); Iterator iter = list.iterator(); sb.append('['); while (iter.hasNext()) { if (first) { first = false; } else { sb.append(','); } Object value = iter.next(); if (value == null) { sb.append("null"); continue; } sb.append(JSONValue.toJSONString(value)); } sb.append(']'); return sb.toString(); } /** * Returns a JSON string representation of this list. * * @return A string. */ @Override public String toJSONString(){ return toJSONString(this); } /** * Returns a string representation of this list. * * @return A string. */ @Override public String toString() { return toJSONString(); } } orson-charts-2.1.0/src/main/java/org/jfree/chart3d/util/json/JSONAware.java000066400000000000000000000023021417331271500263250ustar00rootroot00000000000000/* ============ * Orson Charts * ============ * * (C)opyright 2013-2022, by David Gilbert. * * https://github.com/jfree/orson-charts * * JSON.simple * ----------- * The code in this file originates from the JSON.simple project by * FangYidong: * * https://code.google.com/p/json-simple/ * * which is licensed under the Apache Software License version 2.0. * * It has been modified locally and repackaged under * org.jfree.chart3d.util.json.* to avoid conflicts with any other version that * may be present on the classpath. * */ package org.jfree.chart3d.util.json; /** * Classes that support customized output of JSON text shall implement this * interface. *

* This class is for internal use by Orson Charts, it is not * part of the supported API and you should not call it directly. If you need * JSON support in your project you should include JSON.simple * (https://code.google.com/p/json-simple/) or some other JSON library directly * in your project. */ public interface JSONAware { /** * Returns a JSON string representing the object. * * @return A JSON string. */ String toJSONString(); } orson-charts-2.1.0/src/main/java/org/jfree/chart3d/util/json/JSONObject.java000066400000000000000000000122761417331271500265070ustar00rootroot00000000000000/* ============ * Orson Charts * ============ * * (C)opyright 2013-2022, by David Gilbert. * * https://github.com/jfree/orson-charts * * JSON.simple * ----------- * The code in this file originates from the JSON.simple project by * FangYidong: * * https://code.google.com/p/json-simple/ * * which is licensed under the Apache Software License version 2.0. * * It has been modified locally and repackaged under * org.jfree.chart3d.util.json.* to avoid conflicts with any other version that * may be present on the classpath. * */ package org.jfree.chart3d.util.json; import java.io.IOException; import java.io.Writer; import java.util.HashMap; import java.util.Iterator; import java.util.Map; /** * A JSON object. Key value pairs are unordered. */ public class JSONObject extends HashMap implements Map, JSONAware, JSONStreamAware { private static final long serialVersionUID = -503443796854799292L; /** * Encode a map into JSON text and write it to out. * If this map is also a {@link JSONAware} or {@link JSONStreamAware}, * {@code JSONAware} or {@code JSONStreamAware} specific * behaviours will be ignored at this top level. * * @see org.jfree.chart3d.util.json.JSONValue#writeJSONString(Object, Writer) * * @param map the map to write ({@code null} permitted). * @param out the output writer ({@code null} not permitted). * * @throws IOException if there is an I/O problem. */ public static void writeJSONString(Map map, Writer out) throws IOException { if (map == null) { out.write("null"); return; } boolean first = true; Iterator iter = map.entrySet().iterator(); out.write('{'); while (iter.hasNext()) { if (first) { first = false; } else { out.write(','); } Map.Entry entry = (Map.Entry) iter.next(); out.write('\"'); out.write(JSONValue.escape(String.valueOf(entry.getKey()))); out.write('\"'); out.write(':'); JSONValue.writeJSONString(entry.getValue(), out); } out.write('}'); } /** * Writes a JSON string representing this object instance to the specified * output writer. * * @param out the output writer ({@code null} not permitted). * * @throws IOException if there is an I/O problem. */ @Override public void writeJSONString(Writer out) throws IOException { writeJSONString(this, out); } /** * Convert a map to JSON text. The result is a JSON object. * If this map is also a {@link JSONAware}, {@code JSONAware} specific * behaviours will be omitted at this top level. * * @see org.jfree.chart3d.util.json.JSONValue#toJSONString(Object) * * @param map the map ({@code null} permitted). * * @return JSON text, or "null" if map is null. */ public static String toJSONString(Map map){ if (map == null) { return "null"; } StringBuffer sb = new StringBuffer(); boolean first = true; Iterator iter = map.entrySet().iterator(); sb.append('{'); while (iter.hasNext()) { if (first) { first = false; } else { sb.append(','); } Map.Entry entry = (Map.Entry) iter.next(); toJSONString(String.valueOf(entry.getKey()), entry.getValue(), sb); } sb.append('}'); return sb.toString(); } /** * Returns a JSON string representing this object. * * @return A JSON string. */ @Override public String toJSONString(){ return toJSONString(this); } /** * Writes a key and value to a JSON string. * * @param key the key ({@code null} permitted). * @param value the value ({@code null} permitted). * @param sb a string buffer ({@code null} not permitted). * * @return A JSON string fragment representing the key and value. */ private static String toJSONString(String key, Object value, StringBuffer sb) { sb.append('\"'); if (key == null) { sb.append("null"); } else { JSONValue.escape(key, sb); } sb.append('\"').append(':'); sb.append(JSONValue.toJSONString(value)); return sb.toString(); } /** * Returns a string representation of this object. * * @return A string. */ @Override public String toString(){ return toJSONString(); } /** * Returns a JSON string fragment containing the key and value. * * @param key the key ({@code null} permitted). * @param value the value ({@code null} permitted). * * @return A JSON string fragment. */ public static String toString(String key, Object value){ StringBuffer sb = new StringBuffer(); toJSONString(key, value, sb); return sb.toString(); } } orson-charts-2.1.0/src/main/java/org/jfree/chart3d/util/json/JSONStreamAware.java000066400000000000000000000021171417331271500275050ustar00rootroot00000000000000/* ============ * Orson Charts * ============ * * (C)opyright 2013-2022, by David Gilbert. * * https://github.com/jfree/orson-charts * * JSON.simple * ----------- * The code in this file originates from the JSON.simple project by * FangYidong: * * https://code.google.com/p/json-simple/ * * which is licensed under the Apache Software License version 2.0. * * It has been modified locally and repackaged under * org.jfree.chart3d.util.json.* to avoid conflicts with any other version that * may be present on the classpath. * */ package org.jfree.chart3d.util.json; import java.io.IOException; import java.io.Writer; /** * Beans that support customized output of JSON text to a writer shall implement this interface. * @author FangYidong<fangyidong@yahoo.com.cn> */ public interface JSONStreamAware { /** * write JSON string to out. * * @param out the output writer. * * @throws IOException if there is an I/O problem. */ void writeJSONString(Writer out) throws IOException; } orson-charts-2.1.0/src/main/java/org/jfree/chart3d/util/json/JSONValue.java000066400000000000000000000234241417331271500263520ustar00rootroot00000000000000/* ============ * Orson Charts * ============ * * (C)opyright 2013-2022, by David Gilbert. * * https://github.com/jfree/orson-charts * * JSON.simple * ----------- * The code in this file originates from the JSON.simple project by * FangYidong: * * https://code.google.com/p/json-simple/ * * which is licensed under the Apache Software License version 2.0. * * It has been modified locally and repackaged under * org.jfree.chart3d.util.json.* to avoid conflicts with any other version that * may be present on the classpath. * */ package org.jfree.chart3d.util.json; import java.io.IOException; import java.io.Reader; import java.io.StringReader; import java.io.Writer; import java.util.List; import java.util.Map; import org.jfree.chart3d.util.json.parser.JSONParser; import org.jfree.chart3d.util.json.parser.ParseException; /** * Utility methods for JSON values. */ public class JSONValue { /** * Parse JSON text into java object from the input source. * Please use parseWithException() if you don't want to ignore the * exception. * * @see org.jfree.chart3d.util.json.parser.JSONParser#parse(Reader) * @see #parseWithException(Reader) * * @param in the input reader. * @return Instance of the following: * org.jfree.chart3d.util.json.JSONObject, * org.jfree.chart3d.util.json.JSONArray, * java.lang.String, * java.lang.Number, * java.lang.Boolean, * null */ public static Object parse(Reader in){ try { JSONParser parser = new JSONParser(); return parser.parse(in); } catch (Exception e) { return null; } } /** * Parses an object from a string. * * @param s the string. * * @return An object. */ public static Object parse(String s){ StringReader in = new StringReader(s); return parse(in); } /** * Parse JSON text into java object from the input source. * * @see org.jfree.chart3d.util.json.parser.JSONParser * * @param in the input reader ({@code null} not permitted). * * @return Instance of the following: * org.jfree.chart3d.util.json.JSONObject, * org.jfree.chart3d.util.json.JSONArray, * java.lang.String, * java.lang.Number, * java.lang.Boolean, * null * * @throws IOException if there is an I/O problem. * @throws ParseException if there is a parsing problem. */ public static Object parseWithException(Reader in) throws IOException, ParseException{ JSONParser parser = new JSONParser(); return parser.parse(in); } /** * Parses an object from a JSON string. * * @param s the string. * * @return An object. * * @throws ParseException if there is a parsing problem. */ public static Object parseWithException(String s) throws ParseException{ JSONParser parser = new JSONParser(); return parser.parse(s); } /** * Encode an object into JSON text and write it to out. *

* If this object is a {@code Map} or a {@code List}, and it's * also a {@link JSONStreamAware} or a {@link JSONAware}, * {@code JSONStreamAware} or {@code JSONAware} will be * considered firstly. *

* DO NOT call this method from writeJSONString(Writer) of a class that * implements both JSONStreamAware and (Map or List) with * "this" as the first parameter, use JSONObject.writeJSONString(Map, * Writer) or JSONArray.writeJSONString(List, Writer) instead. * * @see org.jfree.chart3d.util.json.JSONObject#writeJSONString(Map, Writer) * @see org.jfree.chart3d.util.json.JSONArray#writeJSONString(List, Writer) * * @param value the value. * @param out the output writer. * @throws IOException if there is an I/O problem. */ public static void writeJSONString(Object value, Writer out) throws IOException { if (value == null) { out.write("null"); return; } if (value instanceof String) { out.write('\"'); out.write(escape((String) value)); out.write('\"'); return; } if (value instanceof Double) { if(((Double) value).isInfinite() || ((Double) value).isNaN()) { out.write("null"); } else { out.write(value.toString()); } return; } if (value instanceof Float) { if (((Float) value).isInfinite() || ((Float) value).isNaN()) { out.write("null"); } else { out.write(value.toString()); } return; } if (value instanceof Number) { out.write(value.toString()); return; } if (value instanceof Boolean) { out.write(value.toString()); return; } if ((value instanceof JSONStreamAware)) { ((JSONStreamAware) value).writeJSONString(out); return; } if ((value instanceof JSONAware)) { out.write(((JSONAware) value).toJSONString()); return; } if (value instanceof Map) { JSONObject.writeJSONString((Map) value, out); return; } if (value instanceof List) { JSONArray.writeJSONString((List) value, out); return; } out.write(value.toString()); } /** * Convert an object to JSON text. *

* If this object is a Map or a List, and it's also a JSONAware, JSONAware * will be considered firstly. *

* DO NOT call this method from toJSONString() of a class that implements * both JSONAware and Map or List with * "this" as the parameter, use JSONObject.toJSONString(Map) or * JSONArray.toJSONString(List) instead. * * @see org.jfree.chart3d.util.json.JSONObject#toJSONString(Map) * @see org.jfree.chart3d.util.json.JSONArray#toJSONString(List) * * @param value the value. * @return JSON text, or "null" if value is null or it's an NaN or an INF * number. */ public static String toJSONString(Object value){ if (value == null) { return "null"; } if (value instanceof String) { return "\"" + escape((String) value) + "\""; } if (value instanceof Double){ if(((Double) value).isInfinite() || ((Double) value).isNaN()) { return "null"; } else { return value.toString(); } } if (value instanceof Float) { if (((Float) value).isInfinite() || ((Float) value).isNaN()) { return "null"; } else { return value.toString(); } } if (value instanceof Number) { return value.toString(); } if (value instanceof Boolean) { return value.toString(); } if ((value instanceof JSONAware)) { return ((JSONAware) value).toJSONString(); } if (value instanceof Map) { return JSONObject.toJSONString((Map) value); } if (value instanceof List) { return JSONArray.toJSONString((List) value); } return value.toString(); } /** * Escape quotes, \, /, \r, \n, \b, \f, \t and other control characters * (U+0000 through U+001F). * * @param s the string to be escaped ({@code null} permitted). * * @return A string. */ public static String escape(String s) { if (s == null) { return null; } StringBuffer sb = new StringBuffer(); escape(s, sb); return sb.toString(); } /** * Appends the string to a buffer with certain characters escaped. * @param s Must not be null. * @param sb a string buffer */ static void escape(String s, StringBuffer sb) { for(int i = 0; i < s.length(); i++) { char ch = s.charAt(i); switch(ch){ case '"': sb.append("\\\""); break; case '\\': sb.append("\\\\"); break; case '\b': sb.append("\\b"); break; case '\f': sb.append("\\f"); break; case '\n': sb.append("\\n"); break; case '\r': sb.append("\\r"); break; case '\t': sb.append("\\t"); break; case '/': sb.append("\\/"); break; default: //Reference: http://www.unicode.org/versions/Unicode5.1.0/ if ((ch >= '\u0000' && ch <= '\u001F') || (ch >= '\u007F' && ch <= '\u009F') || (ch >= '\u2000' && ch <= '\u20FF')) { String ss = Integer.toHexString(ch); sb.append("\\u"); for (int k = 0; k < 4 - ss.length(); k++) { sb.append('0'); } sb.append(ss.toUpperCase()); } else { sb.append(ch); } } }//for } } orson-charts-2.1.0/src/main/java/org/jfree/chart3d/util/json/package-info.java000066400000000000000000000007441417331271500271300ustar00rootroot00000000000000/** * A local copy of the JSON.simple project by * FangYidong<fangyidong@yahoo.com.cn>: https://code.google.com/p/json-simple/. * This package is for internal use by Orson Charts, it is not * part of the supported API and you should not use it directly. If you need * JSON support in your project you should include JSON.simple * (https://code.google.com/p/json-simple/) or some other JSON library directly * in your project. */ package org.jfree.chart3d.util.json;orson-charts-2.1.0/src/main/java/org/jfree/chart3d/util/json/parser/000077500000000000000000000000001417331271500252305ustar00rootroot00000000000000orson-charts-2.1.0/src/main/java/org/jfree/chart3d/util/json/parser/ContainerFactory.java000066400000000000000000000024011417331271500313420ustar00rootroot00000000000000/* ============ * Orson Charts * ============ * * (C)opyright 2013-2022, by David Gilbert. * * https://github.com/jfree/orson-charts * * JSON.simple * ----------- * The code in this file originates from the JSON.simple project by * FangYidong: * * https://code.google.com/p/json-simple/ * * which is licensed under the Apache Software License version 2.0. * * It has been modified locally and repackaged under * org.jfree.chart3d.util.json.* to avoid conflicts with any other version that * may be present on the classpath. * */ package org.jfree.chart3d.util.json.parser; import java.util.List; import java.util.Map; /** * Container factory for creating containers for JSON object and JSON array. * * @see org.jfree.chart3d.util.json.parser.JSONParser#parse(java.io.Reader, * ContainerFactory) */ public interface ContainerFactory { /** * @return A Map instance to store JSON object, or null if you want to use * org.jfree.chart3d.util.json.JSONObject. */ Map createObjectContainer(); /** * @return A List instance to store JSON array, or null if you want to use * org.jfree.chart3d.util.json.JSONArray. */ List creatArrayContainer(); } orson-charts-2.1.0/src/main/java/org/jfree/chart3d/util/json/parser/ContentHandler.java000066400000000000000000000110351417331271500310030ustar00rootroot00000000000000/* ============ * Orson Charts * ============ * * (C)opyright 2013-2022, by David Gilbert. * * https://github.com/jfree/orson-charts * * JSON.simple * ----------- * The code in this file originates from the JSON.simple project by * FangYidong: * * https://code.google.com/p/json-simple/ * * which is licensed under the Apache Software License version 2.0. * * It has been modified locally and repackaged under * org.jfree.chart3d.util.json.* to avoid conflicts with any other version that * may be present on the classpath. * */ package org.jfree.chart3d.util.json.parser; import java.io.IOException; /** * A simplified and stoppable SAX-like content handler for stream processing of * JSON text. * * @see org.jfree.chart3d.util.json.parser.JSONParser#parse(java.io.Reader, * ContentHandler, boolean) */ public interface ContentHandler { /** * Receive notification of the beginning of JSON processing. * The parser will invoke this method only once. * * @throws ParseException JSONParser will stop and throw the same * exception to the caller when receiving this exception. * @throws IOException if there is an I/O problem. */ void startJSON() throws ParseException, IOException; /** * Receive notification of the end of JSON processing. * * @throws ParseException if there is a parsing problem. * @throws IOException if there is an I/O problem. */ void endJSON() throws ParseException, IOException; /** * Receive notification of the beginning of a JSON object. * * @return false if the handler wants to stop parsing after return. * @throws ParseException JSONParser will stop and throw the same * exception to the caller when receiving this exception. * @throws IOException if there is an I/O problem. * * @see #endJSON */ boolean startObject() throws ParseException, IOException; /** * Receive notification of the end of a JSON object. * * @return false if the handler wants to stop parsing after return. * @throws ParseException if there is a parsing problem. * @throws IOException if there is an I/O problem. * * @see #startObject */ boolean endObject() throws ParseException, IOException; /** * Receive notification of the beginning of a JSON object entry. * * @param key key of a JSON object entry. * * @return false if the handler wants to stop parsing after return. * @throws ParseException if there is a parsing problem. * @throws IOException if there is an I/O problem. * * @see #endObjectEntry */ boolean startObjectEntry(String key) throws ParseException, IOException; /** * Receive notification of the end of the value of previous object entry. * * @return false if the handler wants to stop parsing after return. * @throws ParseException if there is a parsing problem. * @throws IOException if there is an I/O problem. * * @see #startObjectEntry */ boolean endObjectEntry() throws ParseException, IOException; /** * Receive notification of the beginning of a JSON array. * * @return false if the handler wants to stop parsing after return. * @throws ParseException if there is a parsing problem. * @throws IOException if there is an I/O problem. * * @see #endArray */ boolean startArray() throws ParseException, IOException; /** * Receive notification of the end of a JSON array. * * @return false if the handler wants to stop parsing after return. * @throws ParseException if there is a parsing problem. * @throws IOException if there is an I/O problem. * * @see #startArray */ boolean endArray() throws ParseException, IOException; /** * Receive notification of the JSON primitive values: * java.lang.String, * java.lang.Number, * java.lang.Boolean * null * * @param value instance of the following: * java.lang.String, * java.lang.Number, * java.lang.Boolean, * null * * @return false if the handler wants to stop parsing after return. * @throws ParseException if there is a parsing problem. * @throws IOException if there is an I/O problem. */ boolean primitive(Object value) throws ParseException, IOException; } orson-charts-2.1.0/src/main/java/org/jfree/chart3d/util/json/parser/JSONParser.java000066400000000000000000000527451417331271500300360ustar00rootroot00000000000000/* ============ * Orson Charts * ============ * * (C)opyright 2013-2022, by David Gilbert. * * https://github.com/jfree/orson-charts * * JSON.simple * ----------- * The code in this file originates from the JSON.simple project by * FangYidong: * * https://code.google.com/p/json-simple/ * * which is licensed under the Apache Software License version 2.0. * * It has been modified locally and repackaged under * org.jfree.chart3d.util.json.* to avoid conflicts with any other version that * may be present on the classpath. * */ package org.jfree.chart3d.util.json.parser; import java.io.IOException; import java.io.Reader; import java.io.StringReader; import java.util.LinkedList; import java.util.List; import java.util.Map; import org.jfree.chart3d.util.json.JSONArray; import org.jfree.chart3d.util.json.JSONObject; /** * Parser for JSON text. Please note that JSONParser is NOT thread-safe. */ public class JSONParser { public static final int S_INIT = 0; public static final int S_IN_FINISHED_VALUE = 1;//string,number,boolean,null,object,array public static final int S_IN_OBJECT = 2; public static final int S_IN_ARRAY = 3; public static final int S_PASSED_PAIR_KEY = 4; public static final int S_IN_PAIR_VALUE = 5; public static final int S_END = 6; public static final int S_IN_ERROR = -1; private LinkedList handlerStatusStack; private Yylex lexer = new Yylex((Reader)null); private Yytoken token = null; private int status = S_INIT; private int peekStatus(LinkedList statusStack){ if (statusStack.isEmpty()) { return -1; } return statusStack.getFirst(); } /** * Reset the parser to the initial state without resetting the underlying * reader. */ public void reset(){ token = null; status = S_INIT; handlerStatusStack = null; } /** * Reset the parser to the initial state with a new character reader. * * @param in the new character reader. */ public void reset(Reader in){ lexer.yyreset(in); reset(); } /** * @return The position of the beginning of the current token. */ public int getPosition(){ return lexer.getPosition(); } public Object parse(String s) throws ParseException { return parse(s, (ContainerFactory) null); } public Object parse(String s, ContainerFactory containerFactory) throws ParseException { StringReader in = new StringReader(s); try { return parse(in, containerFactory); } catch(IOException ie){ /* * Actually it will never happen. */ throw new ParseException(-1, ParseException.ERROR_UNEXPECTED_EXCEPTION, ie); } } public Object parse(Reader in) throws IOException, ParseException { return parse(in, (ContainerFactory) null); } /** * Parse JSON text into java object from the input source. * * @param in the input source. * @param containerFactory use this factory to create your own JSON * object and JSON array containers. * @return Instance of the following: * org.jfree.chart3d.util.json.simple.JSONObject, * org.jfree.chart3d.util.json.simple.JSONArray, * java.lang.String, * java.lang.Number, * java.lang.Boolean, * null * * @throws IOException if there is an I/O problem. * @throws ParseException if there is a parsing problem. */ @SuppressWarnings("unchecked") public Object parse(Reader in, ContainerFactory containerFactory) throws IOException, ParseException{ reset(in); LinkedList statusStack = new LinkedList<>(); LinkedList valueStack = new LinkedList<>(); try { do { nextToken(); switch(status) { case S_INIT: switch(token.type) { case Yytoken.TYPE_VALUE: status=S_IN_FINISHED_VALUE; statusStack.addFirst(Integer.valueOf(status)); valueStack.addFirst(token.value); break; case Yytoken.TYPE_LEFT_BRACE: status=S_IN_OBJECT; statusStack.addFirst(Integer.valueOf(status)); valueStack.addFirst(createObjectContainer(containerFactory)); break; case Yytoken.TYPE_LEFT_SQUARE: status=S_IN_ARRAY; statusStack.addFirst(Integer.valueOf(status)); valueStack.addFirst(createArrayContainer(containerFactory)); break; default: status=S_IN_ERROR; }//inner switch break; case S_IN_FINISHED_VALUE: if (token.type == Yytoken.TYPE_EOF) { return valueStack.removeFirst(); } else { throw new ParseException(getPosition(), ParseException.ERROR_UNEXPECTED_TOKEN, token); } case S_IN_OBJECT: switch(token.type) { case Yytoken.TYPE_COMMA: break; case Yytoken.TYPE_VALUE: if (token.value instanceof String) { String key = (String) token.value; valueStack.addFirst(key); status = S_PASSED_PAIR_KEY; statusStack.addFirst(Integer.valueOf(status)); } else{ status = S_IN_ERROR; } break; case Yytoken.TYPE_RIGHT_BRACE: if (valueStack.size() > 1) { statusStack.removeFirst(); valueStack.removeFirst(); status = peekStatus(statusStack); } else{ status = S_IN_FINISHED_VALUE; } break; default: status = S_IN_ERROR; break; }//inner switch break; case S_PASSED_PAIR_KEY: switch(token.type) { case Yytoken.TYPE_COLON: break; case Yytoken.TYPE_VALUE: statusStack.removeFirst(); String key = (String) valueStack.removeFirst(); Map parent = (Map) valueStack.getFirst(); parent.put(key,token.value); status = peekStatus(statusStack); break; case Yytoken.TYPE_LEFT_SQUARE: statusStack.removeFirst(); key = (String) valueStack.removeFirst(); parent = (Map) valueStack.getFirst(); List newArray = createArrayContainer(containerFactory); parent.put(key,newArray); status = S_IN_ARRAY; statusStack.addFirst(Integer.valueOf(status)); valueStack.addFirst(newArray); break; case Yytoken.TYPE_LEFT_BRACE: statusStack.removeFirst(); key = (String) valueStack.removeFirst(); parent = (Map) valueStack.getFirst(); Map newObject = createObjectContainer(containerFactory); parent.put(key, newObject); status = S_IN_OBJECT; statusStack.addFirst(Integer.valueOf(status)); valueStack.addFirst(newObject); break; default: status = S_IN_ERROR; } break; case S_IN_ARRAY: switch(token.type) { case Yytoken.TYPE_COMMA: break; case Yytoken.TYPE_VALUE: List val = (List) valueStack.getFirst(); val.add(token.value); break; case Yytoken.TYPE_RIGHT_SQUARE: if (valueStack.size() > 1) { statusStack.removeFirst(); valueStack.removeFirst(); status = peekStatus(statusStack); } else { status = S_IN_FINISHED_VALUE; } break; case Yytoken.TYPE_LEFT_BRACE: val = (List) valueStack.getFirst(); Map newObject = createObjectContainer(containerFactory); val.add(newObject); status = S_IN_OBJECT; statusStack.addFirst(Integer.valueOf(status)); valueStack.addFirst(newObject); break; case Yytoken.TYPE_LEFT_SQUARE: val = (List) valueStack.getFirst(); List newArray = createArrayContainer(containerFactory); val.add(newArray); status = S_IN_ARRAY; statusStack.addFirst(Integer.valueOf(status)); valueStack.addFirst(newArray); break; default: status = S_IN_ERROR; }//inner switch break; case S_IN_ERROR: throw new ParseException(getPosition(), ParseException.ERROR_UNEXPECTED_TOKEN, token); }//switch if (status == S_IN_ERROR) { throw new ParseException(getPosition(), ParseException.ERROR_UNEXPECTED_TOKEN, token); } } while (token.type != Yytoken.TYPE_EOF); } catch (IOException ie) { throw ie; } throw new ParseException(getPosition(), ParseException.ERROR_UNEXPECTED_TOKEN, token); } private void nextToken() throws ParseException, IOException { token = lexer.yylex(); if (token == null) { token = new Yytoken(Yytoken.TYPE_EOF, null); } } private Map createObjectContainer(ContainerFactory containerFactory) { if (containerFactory == null) { return new JSONObject(); } Map m = containerFactory.createObjectContainer(); if (m == null) { return new JSONObject(); } return m; } private List createArrayContainer(ContainerFactory containerFactory) { if (containerFactory == null) { return new JSONArray(); } List l = containerFactory.creatArrayContainer(); if (l == null) { return new JSONArray(); } return l; } public void parse(String s, ContentHandler contentHandler) throws ParseException { parse(s, contentHandler, false); } public void parse(String s, ContentHandler contentHandler, boolean isResume) throws ParseException{ StringReader in = new StringReader(s); try{ parse(in, contentHandler, isResume); } catch(IOException ie) { /* * Actually it will never happen. */ throw new ParseException(-1, ParseException.ERROR_UNEXPECTED_EXCEPTION, ie); } } public void parse(Reader in, ContentHandler contentHandler) throws IOException, ParseException { parse(in, contentHandler, false); } /** * Stream processing of JSON text. * * @see ContentHandler * * @param in the input. * @param contentHandler the content handler. * @param isResume indicates if it continues previous parsing operation. * If set to true, resume parsing the old stream, and parameter 'in' * will be ignored. If this method is called for the first time in * this instance, isResume will be ignored. * * @throws IOException if there is an I/O problem. * @throws ParseException if there is a parsing problem. */ public void parse(Reader in, ContentHandler contentHandler, boolean isResume) throws IOException, ParseException { if (!isResume) { reset(in); handlerStatusStack = new LinkedList<>(); } else{ if (handlerStatusStack == null) { isResume = false; reset(in); handlerStatusStack = new LinkedList<>(); } } LinkedList statusStack = handlerStatusStack; try { do { switch(status) { case S_INIT: contentHandler.startJSON(); nextToken(); switch(token.type) { case Yytoken.TYPE_VALUE: status=S_IN_FINISHED_VALUE; statusStack.addFirst(Integer.valueOf(status)); if (!contentHandler.primitive(token.value)) { return; } break; case Yytoken.TYPE_LEFT_BRACE: status = S_IN_OBJECT; statusStack.addFirst(Integer.valueOf(status)); if (!contentHandler.startObject()) { return; } break; case Yytoken.TYPE_LEFT_SQUARE: status = S_IN_ARRAY; statusStack.addFirst(Integer.valueOf(status)); if (!contentHandler.startArray()) { return; } break; default: status = S_IN_ERROR; }//inner switch break; case S_IN_FINISHED_VALUE: nextToken(); if (token.type == Yytoken.TYPE_EOF) { contentHandler.endJSON(); status = S_END; return; } else { status = S_IN_ERROR; throw new ParseException(getPosition(), ParseException.ERROR_UNEXPECTED_TOKEN, token); } case S_IN_OBJECT: nextToken(); switch(token.type) { case Yytoken.TYPE_COMMA: break; case Yytoken.TYPE_VALUE: if (token.value instanceof String) { String key = (String) token.value; status = S_PASSED_PAIR_KEY; statusStack.addFirst(Integer.valueOf(status)); if (!contentHandler.startObjectEntry(key)) { return; } } else { status = S_IN_ERROR; } break; case Yytoken.TYPE_RIGHT_BRACE: if (statusStack.size() > 1) { statusStack.removeFirst(); status = peekStatus(statusStack); } else{ status = S_IN_FINISHED_VALUE; } if (!contentHandler.endObject()) { return; } break; default: status = S_IN_ERROR; break; }//inner switch break; case S_PASSED_PAIR_KEY: nextToken(); switch(token.type) { case Yytoken.TYPE_COLON: break; case Yytoken.TYPE_VALUE: statusStack.removeFirst(); status = peekStatus(statusStack); if (!contentHandler.primitive(token.value)) { return; } if (!contentHandler.endObjectEntry()) { return; } break; case Yytoken.TYPE_LEFT_SQUARE: statusStack.removeFirst(); statusStack.addFirst(Integer.valueOf(S_IN_PAIR_VALUE)); status = S_IN_ARRAY; statusStack.addFirst(Integer.valueOf(status)); if (!contentHandler.startArray()) { return; } break; case Yytoken.TYPE_LEFT_BRACE: statusStack.removeFirst(); statusStack.addFirst(Integer.valueOf(S_IN_PAIR_VALUE)); status = S_IN_OBJECT; statusStack.addFirst(Integer.valueOf(status)); if (!contentHandler.startObject()) { return; } break; default: status = S_IN_ERROR; } break; case S_IN_PAIR_VALUE: /* * S_IN_PAIR_VALUE is just a marker to indicate the end of * an object entry, it doesn't proccess any token, * therefore delay consuming token until next round. */ statusStack.removeFirst(); status = peekStatus(statusStack); if (!contentHandler.endObjectEntry()) { return; } break; case S_IN_ARRAY: nextToken(); switch(token.type){ case Yytoken.TYPE_COMMA: break; case Yytoken.TYPE_VALUE: if (!contentHandler.primitive(token.value)) { return; } break; case Yytoken.TYPE_RIGHT_SQUARE: if (statusStack.size() > 1) { statusStack.removeFirst(); status = peekStatus(statusStack); } else{ status = S_IN_FINISHED_VALUE; } if (!contentHandler.endArray()) { return; } break; case Yytoken.TYPE_LEFT_BRACE: status = S_IN_OBJECT; statusStack.addFirst(Integer.valueOf(status)); if (!contentHandler.startObject()) { return; } break; case Yytoken.TYPE_LEFT_SQUARE: status = S_IN_ARRAY; statusStack.addFirst(Integer.valueOf(status)); if (!contentHandler.startArray()) { return; } break; default: status = S_IN_ERROR; }//inner switch break; case S_END: return; case S_IN_ERROR: throw new ParseException(getPosition(), ParseException.ERROR_UNEXPECTED_TOKEN, token); }//switch if (status == S_IN_ERROR) { throw new ParseException(getPosition(), ParseException.ERROR_UNEXPECTED_TOKEN, token); } } while(token.type != Yytoken.TYPE_EOF); } catch (IOException | ParseException | RuntimeException | Error ex) { status = S_IN_ERROR; throw ex; } status = S_IN_ERROR; throw new ParseException(getPosition(), ParseException.ERROR_UNEXPECTED_TOKEN, token); } } orson-charts-2.1.0/src/main/java/org/jfree/chart3d/util/json/parser/ParseException.java000066400000000000000000000067211417331271500310320ustar00rootroot00000000000000/* ============ * Orson Charts * ============ * * (C)opyright 2013-2022, by David Gilbert. * * https://github.com/jfree/orson-charts * * JSON.simple * ----------- * The code in this file originates from the JSON.simple project by * FangYidong: * * https://code.google.com/p/json-simple/ * * which is licensed under the Apache Software License version 2.0. * * It has been modified locally and repackaged under * org.jfree.chart3d.util.json.* to avoid conflicts with any other version that * may be present on the classpath. * */ package org.jfree.chart3d.util.json.parser; /** * ParseException explains why and where the error occurs in source JSON text. * */ public class ParseException extends Exception { private static final long serialVersionUID = -7880698968187728548L; public static final int ERROR_UNEXPECTED_CHAR = 0; public static final int ERROR_UNEXPECTED_TOKEN = 1; public static final int ERROR_UNEXPECTED_EXCEPTION = 2; private int errorType; private Object unexpectedObject; private int position; public ParseException(int errorType){ this(-1, errorType, null); } public ParseException(int errorType, Object unexpectedObject){ this(-1, errorType, unexpectedObject); } public ParseException(int position, int errorType, Object unexpectedObject) { this.position = position; this.errorType = errorType; this.unexpectedObject = unexpectedObject; } public int getErrorType() { return errorType; } public void setErrorType(int errorType) { this.errorType = errorType; } /** * @see org.jfree.chart3d.util.json.parser.JSONParser#getPosition() * * @return The character position (starting with 0) of the input where the * error occurs. */ public int getPosition() { return position; } public void setPosition(int position) { this.position = position; } /** * @see org.jfree.chart3d.util.json.parser.Yytoken * * @return One of the following base on the value of errorType: * ERROR_UNEXPECTED_CHAR java.lang.Character * ERROR_UNEXPECTED_TOKEN org.jfree.chart3d.util.json.simple.parser.Yytoken * ERROR_UNEXPECTED_EXCEPTION java.lang.Exception */ public Object getUnexpectedObject() { return unexpectedObject; } public void setUnexpectedObject(Object unexpectedObject) { this.unexpectedObject = unexpectedObject; } @Override public String toString(){ StringBuilder sb = new StringBuilder(); switch(errorType) { case ERROR_UNEXPECTED_CHAR: sb.append("Unexpected character (").append(unexpectedObject); sb.append(") at position ").append(position).append("."); break; case ERROR_UNEXPECTED_TOKEN: sb.append("Unexpected token ").append(unexpectedObject); sb.append(" at position ").append(position).append("."); break; case ERROR_UNEXPECTED_EXCEPTION: sb.append("Unexpected exception at position ").append(position); sb.append(": ").append(unexpectedObject); break; default: sb.append("Unkown error at position ").append(position).append("."); break; } return sb.toString(); } } orson-charts-2.1.0/src/main/java/org/jfree/chart3d/util/json/parser/Yylex.java000066400000000000000000000466061417331271500272210ustar00rootroot00000000000000/* The following code was generated by JFlex 1.4.2 */ package org.jfree.chart3d.util.json.parser; class Yylex { /** This character denotes the end of file */ public static final int YYEOF = -1; /** initial size of the lookahead buffer */ private static final int ZZ_BUFFERSIZE = 16384; /** lexical states */ public static final int YYINITIAL = 0; public static final int STRING_BEGIN = 2; /** * ZZ_LEXSTATE[l] is the state in the DFA for the lexical state l * ZZ_LEXSTATE[l+1] is the state in the DFA for the lexical state l * at the beginning of a line * l is of the form l = 2*k, k a non negative integer */ private static final int ZZ_LEXSTATE[] = { 0, 0, 1, 1 }; /** * Translates characters to character classes */ private static final String ZZ_CMAP_PACKED = "\11\0\1\7\1\7\2\0\1\7\22\0\1\7\1\0\1\11\10\0"+ "\1\6\1\31\1\2\1\4\1\12\12\3\1\32\6\0\4\1\1\5"+ "\1\1\24\0\1\27\1\10\1\30\3\0\1\22\1\13\2\1\1\21"+ "\1\14\5\0\1\23\1\0\1\15\3\0\1\16\1\24\1\17\1\20"+ "\5\0\1\25\1\0\1\26\uff82\0"; /** * Translates characters to character classes */ private static final char [] ZZ_CMAP = zzUnpackCMap(ZZ_CMAP_PACKED); /** * Translates DFA states to action switch labels. */ private static final int [] ZZ_ACTION = zzUnpackAction(); private static final String ZZ_ACTION_PACKED_0 = "\2\0\2\1\1\2\1\3\1\4\3\1\1\5\1\6"+ "\1\7\1\10\1\11\1\12\1\13\1\14\1\15\5\0"+ "\1\14\1\16\1\17\1\20\1\21\1\22\1\23\1\24"+ "\1\0\1\25\1\0\1\25\4\0\1\26\1\27\2\0"+ "\1\30"; private static int [] zzUnpackAction() { int [] result = new int[45]; int offset = 0; offset = zzUnpackAction(ZZ_ACTION_PACKED_0, offset, result); return result; } private static int zzUnpackAction(String packed, int offset, int [] result) { int i = 0; /* index in packed string */ int j = offset; /* index in unpacked array */ int l = packed.length(); while (i < l) { int count = packed.charAt(i++); int value = packed.charAt(i++); do result[j++] = value; while (--count > 0); } return j; } /** * Translates a state to a row index in the transition table */ private static final int [] ZZ_ROWMAP = zzUnpackRowMap(); private static final String ZZ_ROWMAP_PACKED_0 = "\0\0\0\33\0\66\0\121\0\154\0\207\0\66\0\242"+ "\0\275\0\330\0\66\0\66\0\66\0\66\0\66\0\66"+ "\0\363\0\u010e\0\66\0\u0129\0\u0144\0\u015f\0\u017a\0\u0195"+ "\0\66\0\66\0\66\0\66\0\66\0\66\0\66\0\66"+ "\0\u01b0\0\u01cb\0\u01e6\0\u01e6\0\u0201\0\u021c\0\u0237\0\u0252"+ "\0\66\0\66\0\u026d\0\u0288\0\66"; private static int [] zzUnpackRowMap() { int [] result = new int[45]; int offset = 0; offset = zzUnpackRowMap(ZZ_ROWMAP_PACKED_0, offset, result); return result; } private static int zzUnpackRowMap(String packed, int offset, int [] result) { int i = 0; /* index in packed string */ int j = offset; /* index in unpacked array */ int l = packed.length(); while (i < l) { int high = packed.charAt(i++) << 16; result[j++] = high | packed.charAt(i++); } return j; } /** * The transition table of the DFA */ private static final int ZZ_TRANS [] = { 2, 2, 3, 4, 2, 2, 2, 5, 2, 6, 2, 2, 7, 8, 2, 9, 2, 2, 2, 2, 2, 10, 11, 12, 13, 14, 15, 16, 16, 16, 16, 16, 16, 16, 16, 17, 18, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 4, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 4, 19, 20, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 20, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 5, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 21, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 22, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 23, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 16, 16, 16, 16, 16, 16, 16, 16, -1, -1, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, -1, -1, -1, -1, -1, -1, -1, -1, 24, 25, 26, 27, 28, 29, 30, 31, 32, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 33, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 34, 35, -1, -1, 34, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 36, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 37, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 38, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 39, -1, 39, -1, 39, -1, -1, -1, -1, -1, 39, 39, -1, -1, -1, -1, 39, 39, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 33, -1, 20, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 20, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 35, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 38, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 40, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 41, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 42, -1, 42, -1, 42, -1, -1, -1, -1, -1, 42, 42, -1, -1, -1, -1, 42, 42, -1, -1, -1, -1, -1, -1, -1, -1, -1, 43, -1, 43, -1, 43, -1, -1, -1, -1, -1, 43, 43, -1, -1, -1, -1, 43, 43, -1, -1, -1, -1, -1, -1, -1, -1, -1, 44, -1, 44, -1, 44, -1, -1, -1, -1, -1, 44, 44, -1, -1, -1, -1, 44, 44, -1, -1, -1, -1, -1, -1, -1, -1, }; /* error codes */ private static final int ZZ_UNKNOWN_ERROR = 0; private static final int ZZ_NO_MATCH = 1; private static final int ZZ_PUSHBACK_2BIG = 2; /* error messages for the codes above */ private static final String ZZ_ERROR_MSG[] = { "Unkown internal scanner error", "Error: could not match input", "Error: pushback value was too large" }; /** * ZZ_ATTRIBUTE[aState] contains the attributes of state {@code aState} */ private static final int [] ZZ_ATTRIBUTE = zzUnpackAttribute(); private static final String ZZ_ATTRIBUTE_PACKED_0 = "\2\0\1\11\3\1\1\11\3\1\6\11\2\1\1\11"+ "\5\0\10\11\1\0\1\1\1\0\1\1\4\0\2\11"+ "\2\0\1\11"; private static int [] zzUnpackAttribute() { int [] result = new int[45]; int offset = 0; offset = zzUnpackAttribute(ZZ_ATTRIBUTE_PACKED_0, offset, result); return result; } private static int zzUnpackAttribute(String packed, int offset, int [] result) { int i = 0; /* index in packed string */ int j = offset; /* index in unpacked array */ int l = packed.length(); while (i < l) { int count = packed.charAt(i++); int value = packed.charAt(i++); do result[j++] = value; while (--count > 0); } return j; } /** the input device */ private java.io.Reader zzReader; /** the current state of the DFA */ private int zzState; /** the current lexical state */ private int zzLexicalState = YYINITIAL; /** this buffer contains the current text to be matched and is the source of the yytext() string */ private char zzBuffer[] = new char[ZZ_BUFFERSIZE]; /** the textposition at the last accepting state */ private int zzMarkedPos; /** the current text position in the buffer */ private int zzCurrentPos; /** startRead marks the beginning of the yytext() string in the buffer */ private int zzStartRead; /** endRead marks the last character in the buffer, that has been read from input */ private int zzEndRead; /** number of newlines encountered up to the start of the matched text */ private int yyline; /** the number of characters up to the start of the matched text */ private int yychar; /** * the number of characters from the last newline up to the start of the * matched text */ private int yycolumn; /** * zzAtBOL == true <=> the scanner is currently at the beginning of a line */ private boolean zzAtBOL = true; /** zzAtEOF == true <=> the scanner is at the EOF */ private boolean zzAtEOF; /* user code: */ private StringBuffer sb=new StringBuffer(); int getPosition(){ return yychar; } /** * Creates a new scanner * There is also a java.io.InputStream version of this constructor. * * @param in the java.io.Reader to read input from. */ Yylex(java.io.Reader in) { this.zzReader = in; } /** * Creates a new scanner. * There is also java.io.Reader version of this constructor. * * @param in the java.io.Inputstream to read input from. */ Yylex(java.io.InputStream in) { this(new java.io.InputStreamReader(in)); } /** * Unpacks the compressed character translation table. * * @param packed the packed character translation table * @return the unpacked character translation table */ private static char [] zzUnpackCMap(String packed) { char [] map = new char[0x10000]; int i = 0; /* index in packed string */ int j = 0; /* index in unpacked array */ while (i < 90) { int count = packed.charAt(i++); char value = packed.charAt(i++); do map[j++] = value; while (--count > 0); } return map; } /** * Refills the input buffer. * * @return {@code false}, iff there was new input. * * @exception java.io.IOException if any I/O-Error occurs */ private boolean zzRefill() throws java.io.IOException { /* first: make room (if you can) */ if (zzStartRead > 0) { System.arraycopy(zzBuffer, zzStartRead, zzBuffer, 0, zzEndRead-zzStartRead); /* translate stored positions */ zzEndRead-= zzStartRead; zzCurrentPos-= zzStartRead; zzMarkedPos-= zzStartRead; zzStartRead = 0; } /* is the buffer big enough? */ if (zzCurrentPos >= zzBuffer.length) { /* if not: blow it up */ char newBuffer[] = new char[zzCurrentPos*2]; System.arraycopy(zzBuffer, 0, newBuffer, 0, zzBuffer.length); zzBuffer = newBuffer; } /* finally: fill the buffer with new input */ int numRead = zzReader.read(zzBuffer, zzEndRead, zzBuffer.length-zzEndRead); if (numRead > 0) { zzEndRead+= numRead; return false; } // unlikely but not impossible: read 0 characters, but not at end of stream if (numRead == 0) { int c = zzReader.read(); if (c == -1) { return true; } else { zzBuffer[zzEndRead++] = (char) c; return false; } } // numRead < 0 return true; } /** * Closes the input stream. */ public final void yyclose() throws java.io.IOException { zzAtEOF = true; /* indicate end of file */ zzEndRead = zzStartRead; /* invalidate buffer */ if (zzReader != null) zzReader.close(); } /** * Resets the scanner to read from a new input stream. * Does not close the old reader. * * All internal variables are reset, the old input stream * cannot be reused (internal buffer is discarded and lost). * Lexical state is set to ZZ_INITIAL. * * @param reader the new input stream */ public final void yyreset(java.io.Reader reader) { zzReader = reader; zzAtBOL = true; zzAtEOF = false; zzEndRead = zzStartRead = 0; zzCurrentPos = zzMarkedPos = 0; yyline = yychar = yycolumn = 0; zzLexicalState = YYINITIAL; } /** * Returns the current lexical state. */ public final int yystate() { return zzLexicalState; } /** * Enters a new lexical state * * @param newState the new lexical state */ public final void yybegin(int newState) { zzLexicalState = newState; } /** * Returns the text matched by the current regular expression. */ public final String yytext() { return new String( zzBuffer, zzStartRead, zzMarkedPos-zzStartRead ); } /** * Returns the character at position pos from the * matched text. * * It is equivalent to yytext().charAt(pos), but faster * * @param pos the position of the character to fetch. * A value from 0 to yylength()-1. * * @return the character at position pos */ public final char yycharat(int pos) { return zzBuffer[zzStartRead+pos]; } /** * Returns the length of the matched text region. */ public final int yylength() { return zzMarkedPos-zzStartRead; } /** * Reports an error that occured while scanning. * * In a wellformed scanner (no or only correct usage of * yypushback(int) and a match-all fallback rule) this method * will only be called with things that "Can't Possibly Happen". * If this method is called, something is seriously wrong * (e.g. a JFlex bug producing a faulty scanner etc.). * * Usual syntax/scanner level error handling should be done * in error fallback rules. * * @param errorCode the code of the errormessage to display */ private void zzScanError(int errorCode) { String message; try { message = ZZ_ERROR_MSG[errorCode]; } catch (ArrayIndexOutOfBoundsException e) { message = ZZ_ERROR_MSG[ZZ_UNKNOWN_ERROR]; } throw new Error(message); } /** * Pushes the specified amount of characters back into the input stream. * * They will be read again by then next call of the scanning method * * @param number the number of characters to be read again. * This number must not be greater than yylength()! */ public void yypushback(int number) { if ( number > yylength() ) zzScanError(ZZ_PUSHBACK_2BIG); zzMarkedPos -= number; } /** * Resumes scanning until the next regular expression is matched, * the end of input is encountered or an I/O-Error occurs. * * @return the next token * @exception java.io.IOException if any I/O-Error occurs */ public Yytoken yylex() throws java.io.IOException, ParseException { int zzInput; int zzAction; // cached fields: int zzCurrentPosL; int zzMarkedPosL; int zzEndReadL = zzEndRead; char [] zzBufferL = zzBuffer; char [] zzCMapL = ZZ_CMAP; int [] zzTransL = ZZ_TRANS; int [] zzRowMapL = ZZ_ROWMAP; int [] zzAttrL = ZZ_ATTRIBUTE; while (true) { zzMarkedPosL = zzMarkedPos; yychar+= zzMarkedPosL-zzStartRead; zzAction = -1; zzCurrentPosL = zzCurrentPos = zzStartRead = zzMarkedPosL; zzState = ZZ_LEXSTATE[zzLexicalState]; zzForAction: { while (true) { if (zzCurrentPosL < zzEndReadL) zzInput = zzBufferL[zzCurrentPosL++]; else if (zzAtEOF) { zzInput = YYEOF; break zzForAction; } else { // store back cached positions zzCurrentPos = zzCurrentPosL; zzMarkedPos = zzMarkedPosL; boolean eof = zzRefill(); // get translated positions and possibly new buffer zzCurrentPosL = zzCurrentPos; zzMarkedPosL = zzMarkedPos; zzBufferL = zzBuffer; zzEndReadL = zzEndRead; if (eof) { zzInput = YYEOF; break zzForAction; } else { zzInput = zzBufferL[zzCurrentPosL++]; } } int zzNext = zzTransL[ zzRowMapL[zzState] + zzCMapL[zzInput] ]; if (zzNext == -1) break zzForAction; zzState = zzNext; int zzAttributes = zzAttrL[zzState]; if ( (zzAttributes & 1) == 1 ) { zzAction = zzState; zzMarkedPosL = zzCurrentPosL; if ( (zzAttributes & 8) == 8 ) break zzForAction; } } } // store back cached position zzMarkedPos = zzMarkedPosL; switch (zzAction < 0 ? zzAction : ZZ_ACTION[zzAction]) { case 11: { sb.append(yytext()); } case 25: break; case 4: { sb.delete(0, sb.length());yybegin(STRING_BEGIN); } case 26: break; case 16: { sb.append('\b'); } case 27: break; case 6: { return new Yytoken(Yytoken.TYPE_RIGHT_BRACE,null); } case 28: break; case 23: { Boolean val=Boolean.valueOf(yytext()); return new Yytoken(Yytoken.TYPE_VALUE, val); } case 29: break; case 22: { return new Yytoken(Yytoken.TYPE_VALUE, null); } case 30: break; case 13: { yybegin(YYINITIAL);return new Yytoken(Yytoken.TYPE_VALUE, sb.toString()); } case 31: break; case 12: { sb.append('\\'); } case 32: break; case 21: { Double val=Double.valueOf(yytext()); return new Yytoken(Yytoken.TYPE_VALUE, val); } case 33: break; case 1: { throw new ParseException(yychar, ParseException.ERROR_UNEXPECTED_CHAR, yycharat(0)); } case 34: break; case 8: { return new Yytoken(Yytoken.TYPE_RIGHT_SQUARE,null); } case 35: break; case 19: { sb.append('\r'); } case 36: break; case 15: { sb.append('/'); } case 37: break; case 10: { return new Yytoken(Yytoken.TYPE_COLON,null); } case 38: break; case 14: { sb.append('"'); } case 39: break; case 5: { return new Yytoken(Yytoken.TYPE_LEFT_BRACE,null); } case 40: break; case 17: { sb.append('\f'); } case 41: break; case 24: { try{ int ch=Integer.parseInt(yytext().substring(2),16); sb.append((char)ch); } catch(Exception e){ throw new ParseException(yychar, ParseException.ERROR_UNEXPECTED_EXCEPTION, e); } } case 42: break; case 20: { sb.append('\t'); } case 43: break; case 7: { return new Yytoken(Yytoken.TYPE_LEFT_SQUARE,null); } case 44: break; case 2: { Long val=Long.valueOf(yytext()); return new Yytoken(Yytoken.TYPE_VALUE, val); } case 45: break; case 18: { sb.append('\n'); } case 46: break; case 9: { return new Yytoken(Yytoken.TYPE_COMMA,null); } case 47: break; case 3: { } case 48: break; default: if (zzInput == YYEOF && zzStartRead == zzCurrentPos) { zzAtEOF = true; return null; } else { zzScanError(ZZ_NO_MATCH); } } } } } orson-charts-2.1.0/src/main/java/org/jfree/chart3d/util/json/parser/Yytoken.java000066400000000000000000000041471417331271500275430ustar00rootroot00000000000000/* ============ * Orson Charts * ============ * * (C)opyright 2013-2022, by David Gilbert. * * https://github.com/jfree/orson-charts * * JSON.simple * ----------- * The code in this file originates from the JSON.simple project by * FangYidong: * * https://code.google.com/p/json-simple/ * * which is licensed under the Apache Software License version 2.0. * * It has been modified locally and repackaged under * org.jfree.chart3d.util.json.* to avoid conflicts with any other version that * may be present on the classpath. * */ package org.jfree.chart3d.util.json.parser; /** * */ public class Yytoken { public static final int TYPE_VALUE = 0;//JSON primitive value: string,number,boolean,null public static final int TYPE_LEFT_BRACE = 1; public static final int TYPE_RIGHT_BRACE = 2; public static final int TYPE_LEFT_SQUARE = 3; public static final int TYPE_RIGHT_SQUARE = 4; public static final int TYPE_COMMA = 5; public static final int TYPE_COLON = 6; public static final int TYPE_EOF = -1;//end of file public int type = 0; public Object value = null; public Yytoken(int type,Object value){ this.type=type; this.value=value; } @Override public String toString(){ StringBuilder sb = new StringBuilder(); switch (type) { case TYPE_VALUE: sb.append("VALUE(").append(value).append(")"); break; case TYPE_LEFT_BRACE: sb.append("LEFT BRACE({)"); break; case TYPE_RIGHT_BRACE: sb.append("RIGHT BRACE(})"); break; case TYPE_LEFT_SQUARE: sb.append("LEFT SQUARE([)"); break; case TYPE_RIGHT_SQUARE: sb.append("RIGHT SQUARE(])"); break; case TYPE_COMMA: sb.append("COMMA(,)"); break; case TYPE_COLON: sb.append("COLON(:)"); break; case TYPE_EOF: sb.append("END OF FILE"); break; } return sb.toString(); } } orson-charts-2.1.0/src/main/java/org/jfree/chart3d/util/json/parser/package-info.java000066400000000000000000000007531417331271500304240ustar00rootroot00000000000000/** * A local copy of the JSON.simple project by * FangYidong<fangyidong@yahoo.com.cn>: https://code.google.com/p/json-simple/. * This package is for internal use by Orson Charts, it is not * part of the supported API and you should not use it directly. If you need * JSON support in your project you should include JSON.simple * (https://code.google.com/p/json-simple/) or some other JSON library directly * in your project. */ package org.jfree.chart3d.util.json.parser;orson-charts-2.1.0/src/main/javadoc/000077500000000000000000000000001417331271500172625ustar00rootroot00000000000000orson-charts-2.1.0/src/main/javadoc/doc-files/000077500000000000000000000000001417331271500211275ustar00rootroot00000000000000orson-charts-2.1.0/src/main/javadoc/doc-files/AreaChart3DDemo1.svg000066400000000000000000001053661417331271500245720ustar00rootroot00000000000000 Q1/11Q2/11Q3/11Q4/11Q1/12Q2/12Q3/12Q4/12Q1/13Q2/13Quarter01020304050ValueGoogleMicrosoftAppleOrson Charts (c) 2013, by Object Refinery LimitedReported Revenues By QuarterLarge companies in the IT industry orson-charts-2.1.0/src/main/javadoc/doc-files/BarChart3DDemo1.svg000066400000000000000000002523151417331271500244230ustar00rootroot00000000000000 JanFebMarAprMayJunJulAugSepOctNovDec0510152025Temp °CLondonGenevaBergeracChristchurchWellingtonLondonGenevaBergeracChristchurchWellingtonOrson Charts (c) 2013, by Object Refinery LimitedAverage Maximum Temperaturehttp://www.worldclimateguide.co.uk/climateguides/ orson-charts-2.1.0/src/main/javadoc/doc-files/LineChart3DDemo1.svg000066400000000000000000002127441417331271500246100ustar00rootroot00000000000000 Jan-12Feb-12Mar-12Apr-12May-12Jun-12Jul-12Aug-12Sep-12Oct-12Nov-12Dec-12Jan-13Feb-13Mar-13Apr-13May-13Jun-1310%20%30%40%Market Share (%)SafariFirefoxInternet ExplorerChromeOrson Charts (c) 2013, by Object Refinery LimitedWeb Browser Market ShareSource: http://gs.statcounter.com orson-charts-2.1.0/src/main/javadoc/doc-files/PieChart3DDemo1.svg000066400000000000000000001644131417331271500244350ustar00rootroot00000000000000 Milk ProductsMeatWood/LogsCrude OilMachineryFruitFishWineOtherMilk ProductsMeatWood/LogsCrude OilMachineryFruitFishWineOtherOrson Charts (c) 2013, by Object Refinery LimitedNew Zealand Exports 2012http://www.stats.govt.nz/browse_for_stats/snapshots-of-nz/nz-in-profile-2013.aspx orson-charts-2.1.0/src/main/javadoc/doc-files/ScatterPlot3DDemo1.svg000066400000000000000000004257321417331271500252060ustar00rootroot00000000000000 0102030405060708090100X0.0000.0020.0040.0060.0080.010Y050100ZS1S2S3Orson Charts (c) 2013, by Object Refinery LimitedScatterPlot3DDemo1Chart created with Orson Charts orson-charts-2.1.0/src/main/javadoc/doc-files/ScatterPlot3DDemo2.svg000066400000000000000000053660221417331271500252100ustar00rootroot00000000000000 0.00.51.01.52.02.53.03.54.04.55.05.56.0X-1.0-0.50.00.51.0Y0246Zy = cos(x) * sin(z)Orson Charts (c) 2013, by Object Refinery LimitedScatterPlot3DDemo2Chart created with Orson Charts orson-charts-2.1.0/src/main/javadoc/doc-files/StackedBarChart3DDemo1.svg000066400000000000000000001342071417331271500257210ustar00rootroot00000000000000 ABCDEF051015ValueRow 1Row 2Row 3Series 1Series 2Series 3Series 4Series 5Orson Charts (c) 2013, by Object Refinery LimitedStacked Bar ChartPut the data source here orson-charts-2.1.0/src/main/javadoc/doc-files/SurfaceRendererDemo2.svg000066400000000000000000012776601417331271500256410ustar00rootroot00000000000000 -2.0-1.5-1.0-0.50.00.51.01.52.0X-1.0-0.50.00.51.0Y-2.0-1.5-1.0-0.50.00.51.01.52.0Z-1.001.00Orson Charts (evaluation) (c) 2013, by Object Refinery LimitedSurfaceRendererDemo2y = sin(x^2 + z^2) orson-charts-2.1.0/src/main/javadoc/doc-files/XYZBarChart3DDemo1.svg000066400000000000000000000416571417331271500250430ustar00rootroot00000000000000 1.01.52.0X0246810Value1.01.52.0ZSeries 1Series 2Series 3Orson Charts (c) 2013, by Object Refinery LimitedXYZBarChart3DDemo1Chart created with Orson Charts orson-charts-2.1.0/src/main/javadoc/org/000077500000000000000000000000001417331271500200515ustar00rootroot00000000000000orson-charts-2.1.0/src/main/javadoc/org/jfree/000077500000000000000000000000001417331271500211445ustar00rootroot00000000000000orson-charts-2.1.0/src/main/javadoc/org/jfree/chart3d/000077500000000000000000000000001417331271500224745ustar00rootroot00000000000000orson-charts-2.1.0/src/main/javadoc/org/jfree/chart3d/renderer/000077500000000000000000000000001417331271500243025ustar00rootroot00000000000000orson-charts-2.1.0/src/main/javadoc/org/jfree/chart3d/renderer/doc-files/000077500000000000000000000000001417331271500261475ustar00rootroot00000000000000orson-charts-2.1.0/src/main/javadoc/org/jfree/chart3d/renderer/doc-files/BarRenderer3D.svg000066400000000000000000003610621417331271500312620ustar00rootroot00000000000000 GoogleMicrosoftAppleBarChart3DDemo1 orson-charts-2.1.0/src/main/resources/000077500000000000000000000000001417331271500176655ustar00rootroot00000000000000orson-charts-2.1.0/src/main/resources/org/000077500000000000000000000000001417331271500204545ustar00rootroot00000000000000orson-charts-2.1.0/src/main/resources/org/jfree/000077500000000000000000000000001417331271500215475ustar00rootroot00000000000000orson-charts-2.1.0/src/main/resources/org/jfree/chart3d/000077500000000000000000000000001417331271500230775ustar00rootroot00000000000000orson-charts-2.1.0/src/main/resources/org/jfree/chart3d/Resources.properties000066400000000000000000000016241417331271500271720ustar00rootroot00000000000000# Resources for localisation. These strings are referenced in the source # code by key only, and can be localised by creating locale-specific properties # files # Popup menu items ZOOM_IN = Zoom In ZOOM_OUT = Zoom Out ZOOM_TO_FIT = Zoom To Fit EXPORT_AS = Export As JPG_MENU_LABEL = JPEG... PDF_MENU_LABEL = PDF... PNG_MENU_LABEL = PNG... SVG_MENU_LABEL = SVG... # Toolbar action tooltips UP_ACTION_SHORT_DESCRIPTION = Rotate up DOWN_ACTION_SHORT_DESCRIPTION = Rotate down LEFT_ACTION_SHORT_DESCRIPTION = Rotate to the left RIGHT_ACTION_SHORT_DESCRIPTION = Rotate to the right ROLL_LEFT_ACTION_SHORT_DESCRIPTION = Roll counter-clockwise ROLL_RIGHT_ACTION_SHORT_DESCRIPTION = Roll clockwise # File filter items JPG_FILE_FILTER_DESCRIPTION = JPG Files PDF_FILE_FILTER_DESCRIPTION = Portable Document Format (PDF) PNG_FILE_FILTER_DESCRIPTION = PNG Files SVG_FILE_FILTER_DESCRIPTION = Scalable Vector Graphics (SVG) orson-charts-2.1.0/src/main/resources/org/jfree/chart3d/Resources_de.properties000066400000000000000000000017701417331271500276440ustar00rootroot00000000000000# Resources for localisation. These strings are referenced in the source # code by key only, and can be localised by creating locale-specific properties # files # German translation provided by Roman Kennke # Popup menu items ZOOM_IN = Vergr\u00f6\u00dfern ZOOM_OUT = Verkleinern ZOOM_TO_FIT = Einpassen EXPORT_AS = Exportieren als JPG_MENU_LABEL = JPEG... PDF_MENU_LABEL = PDF... PNG_MENU_LABEL = PNG... SVG_MENU_LABEL = SVG... # Toolbar action tooltips UP_ACTION_SHORT_DESCRIPTION = Nach oben rotieren DOWN_ACTION_SHORT_DESCRIPTION = Nach unten rotieren LEFT_ACTION_SHORT_DESCRIPTION = Nach links rotieren RIGHT_ACTION_SHORT_DESCRIPTION = Nach rechts rotieren ROLL_LEFT_ACTION_SHORT_DESCRIPTION = Gegen Urzeigersinn rollen ROLL_RIGHT_ACTION_SHORT_DESCRIPTION = Im Urzeigersinn rollen # File filter items JPG_FILE_FILTER_DESCRIPTION = JPG Dateien PDF_FILE_FILTER_DESCRIPTION = Portable Document Format (PDF) PNG_FILE_FILTER_DESCRIPTION = PNG Dateien SVG_FILE_FILTER_DESCRIPTION = Scalable Vector Graphics (SVG)orson-charts-2.1.0/src/main/resources/org/jfree/chart3d/Resources_it.properties000066400000000000000000000017131417331271500276650ustar00rootroot00000000000000# Resources for localisation. These strings are referenced in the source # code by key only, and can be localised by creating locale-specific properties # files # Italian translation provided by Mario Torre # Popup menu items ZOOM_IN = Ingrandisci ZOOM_OUT = Riduci ZOOM_TO_FIT = Adatta EXPORT_AS = Esporta Come JPG_MENU_LABEL = JPEG... PDF_MENU_LABEL = PDF... PNG_MENU_LABEL = PNG... SVG_MENU_LABEL = SVG... # Toolbar action tooltips UP_ACTION_SHORT_DESCRIPTION = Ruota in su DOWN_ACTION_SHORT_DESCRIPTION = Ruota in gi\u00f9 LEFT_ACTION_SHORT_DESCRIPTION = Gira a sinistra RIGHT_ACTION_SHORT_DESCRIPTION = Gira a destra ROLL_LEFT_ACTION_SHORT_DESCRIPTION = Ruota in senso antiorario ROLL_RIGHT_ACTION_SHORT_DESCRIPTION = Ruota in senso orario # File filter items JPG_FILE_FILTER_DESCRIPTION = JPG Files PDF_FILE_FILTER_DESCRIPTION = Portable Document Format (PDF) PNG_FILE_FILTER_DESCRIPTION = PNG Files SVG_FILE_FILTER_DESCRIPTION = Scalable Vector Graphics (SVG)orson-charts-2.1.0/src/main/resources/org/jfree/chart3d/graphics3d/000077500000000000000000000000001417331271500251265ustar00rootroot00000000000000orson-charts-2.1.0/src/main/resources/org/jfree/chart3d/graphics3d/swing/000077500000000000000000000000001417331271500262555ustar00rootroot00000000000000orson-charts-2.1.0/src/main/resources/org/jfree/chart3d/graphics3d/swing/fontawesome-webfont.ttf000077500000000000000000002354141417331271500330010ustar00rootroot00000000000000€`FFTMf/WìGDEFà OS/2‹z(`cmapÑk¼ˆrgaspüglyf;eªôheadÜ«ø6hhea ‚ë0$hmtxìTHloca©8b€#œ.maxpì&Ì name;úež&ì¸postP¯ú)¤]webf¹ØRw;Ì=¢ÏËT‚0ÎjW•äŒ3†Œ3sZ3pyrs@ õÿ# lPP@  ©®´Æ / _!"""`àððð>ðNð^ðnð~ðŽðžð®ð²ðÎðÞðîðþñññ.ñ>ñNñ^ñnñ~ñŽñžõÿÿ  ¨®´Æ / _!"""`àððð!ð@ðPð`ðpð€ðð ð°ðÀðÐðàððñññ ñ0ñ@ñPñ`ñpñ€ñõÿÿÿãÿdÿ]ÿYÿTÿCà ßæß·ÞõÝúݹ ÿþýüûúùø÷ö • ÿÿp7!!!àÀþ@p p úpú1]ÿ£€!2#!"&463!&54>3!2£+ýˆ@&&ü€&&@ýˆ+$(€($F#+ýˆý&4&&4&x+#ÿ€+".4>32".4>32467632DhgZghDDhg-iWýDhgZghDDhg-iW&@ (8 û 2N++NdN+'íý;2N++NdN+'Ç3 8ÿ€€!  #"'#"$&6$ €þùþŽþùrL46$þ©³Üþû½oo½½o|W%rþùþŽþùþ€4L&V|o½½oo½þûܳþ©%ÿ€=M%+".'&%&'3!26<.#!";2>767>7#!"&5463!2€ %þôž3@m00m@3žþô%  À  ú@ “ÁÐ:"7..7":ÐÁ6]€^Bú@B^^BÀB^ $΄+0110+„Î$ý (   ¨t˜¥1%%1¥˜+‘`ûÀB^^B@B^^ÿ€€"'.54632>32š4ý #LoP$$Po>àþåý‘€Z$_dŽCÜø+I@$$@I+øÜÝåý¨ÿ­€à"#"'%#"&547&547%62€þ•Vþ?þ?Vþ”8öá<áö8yþžþ   ìì ôb% IÇ))þ9I ÿ­€à + % %#"'%#"&547&547%62q2þZ½½þZ2IzyÇþ•V)þ?þ?Vþ”8öá<áö8)>~þ‚>þ×þ[ÇÇ þžþ  2 ìì ôb% IÇ))þ9I ÿ€€€'%#!"&54>322>32 &6 €’yü–y’ 6Fe= BS…†…SB =eF6 þÀáþÂáá>ƒx‹‹x5eud_C(+5++5+(C_dueçþÂáá>á ÿ€€/?O_oŸ¯54&+";2654&+";2654&+";264&#!"3!2654&+";2654&+";264&#!"3!2654&+";2654&+";2654&+";267#!"&5463!2€&€&&€&&€&&€&&€&&€&&ý&&&ü&€&&€&€&€&&€&þ€&ý&&&€&€&&€&&€&&€&&€&&€&€^BùÀB^^B@B^@€&&€&&š€&&€&&š€&&€&&ý&&þ&&š€&&€&&ûš€&&€&&&&þ&&þš€&&€&&š€&&€&&š€&&€&&ºúÀB^^B@B^^€€/?#!"&5463!2#!"&5463!2#!"&5463!2#!"&5463!2L4þ4LL44LL4þ4LL44L€L4þ4LL44LL4þ4LL44Lþ€4LL4€4LLÌþ€4LL4€4LLüÌþ€4LL4€4LLÌþ€4LL4€4LL €/?O_o#!"&=463!2#!"&=463!2#!"&=463!2#!"&=463!2#!"&=463!2#!"&=463!2#!"&=463!2#!"&=463!2#!"&=463!28(þÀ(88(@(88(þÀ(88(@(8€8(þÀ(88(@(8ý€8(þÀ(88(@(8€8(þÀ(88(@(8€8(þÀ(88(@(8ý€8(þÀ(88(@(8€8(þÀ(88(@(88(þÀ(88(@(8 À(88(À(88ØÀ(88(À(88ýØÀ(88(À(88ØÀ(88(À(88ýØÀ(88(À(88ýØÀ(88(À(88ØÀ(88(À(88ýØÀ(88(À(88ØÀ(88(À(88€/?O_#!"&=463!2#!"&=463!2#!"&=463!2#!"&=463!2#!"&=463!2#!"&=463!28(þÀ(88(@(88(þÀ(88(@(88(ü@(88(À(8û8(þÀ(88(@(88(ü@(88(À(88(ü@(88(À(8 À(88(À(88ØÀ(88(À(88ýØÀ(88(À(88ØÀ(88(À(88ýØÀ(88(À(88ØÀ(88(À(88y‡²"/&4?62 62‡ý,ˆPˆþ–ˆP&PˆòPý,ˆˆjPˆþÙ‘ˆnÿî’#$"' "/&47 &4?62 62 ˆPþÚþÚPˆ&þÚˆP&&PˆþÚ&þPˆ&þÚˆP&&PˆþÚ&ˆPþÚþÚÿ€€#+D++"&=#"&=46;546;232  #"'#"$&6$  à @ à  à @ à €þùþŽþùrK56$þ©³Üþû½oo½½o|Wà@ à  à @ à  àærþùþŽþùþµjK&V|o½½oo½þûܳþ©ÿ€€0#!"&=463!2  #"'#"$&6$  ýÀ  @ €þùþŽþùrK56$þ©³Üþû½oo½½o|Wà@  @ ærþùþŽþùþµjK&V|o½½oo½þûܳþ©ÿ€)5 $&54762>54&'.7>"&5462zÎþäþÈþäÎz¡’+i *bkQŠ½Ð½ŠQkb* j*’¡ý€LhLLhL€œþäÎzzΜ¶Bm +*i JÖyh½ŠQQнhyÖJ i*+ mþ¾Jý€4LL4€4LLÿ€€/?O%+"&=46;2%+"&546;2%+"&546;2+"&546;2+"&546;2ÀÀ€ÀÀ€ÀÀ€ÀÀ€ÀÀ`ÀÀrþÀ@òýÀ@rü@Àòú@Àÿ€€n4&"2#"/+"&/&'#"'&'&547>7&/.=46?67&'&547>3267676;27632–Ô––Ô– ¹#H  Š,/ Þ1)  ~'H·  º(C ‘ Š,/ Þ1)Ž  $H· Ô––Ô–mÞ 6%2X  %Ž lˆ2 ¸k r6 [21 Þ ..9Q $ kˆ2 ¸k w3 [20ÿ€€€/;Cg+"&546;2+"&546;2+"&546;2!3!2>!'&'!+#!"&5#"&=463!7>3!2!2@@@@@@€ü€@ý`À0 þà o`^BüÀB^`5FN(@(NF5 ýÀ@ýÀ@ýÀ@ý´üL%%Ju  •@üLSyuS¸@§%44%§f5#!!!"&5465 7#"' '&/&6762546;2€&þ€ÿþ€&??ß>  ýLýL > Ï X ôÀÛ  þ &€þ€&àÚþ&AJ Aý¿ J WÌÃþh¶ÿ€€#3!!"&5!!&'&'#!"&5463!2€þ`(8þ€x þÇ 8(ûÀ(88(€(`8(8( þ€ 9 þhü€(88(@(8(þÈ`ÿ€€ ,#!"&=46;46;2.  6 $$ €þÀà@ ’úþØú’’ú(úrÎþŸþ^þŸÎÎa¢aàþ@@`ýþ(ú’’úþØú’’_þ^þŸÎÎa¢aÎÎ2NC5.+";26#!26'.#!"3!"547>3!";26/.#!2W º  ô ö.ý@  þð  ý@.¡$S  ¦  S$¡@  þÀ þ9I   ÿ I6> ÀÀ ûì>€%=$4&"2$4&"2#!"&5463!2?!2"'&763!463!2!2&4&&4&&4&&4¦8(ú@(88(ч:œ:ˆÐ(8þ»þ@6þ@*&&*¦4&&4&&4&&4& þÀ(88(@(8ˆ88ˆ8)þ@À)'À&&þ@ÿ€€$0"'&76;46;232  >& $$ ` þÁ  þÀÀÀÀÌþØú’’ú(ú’’rÎþŸþ^þŸÎÎa¢a` þÁ @`þ 2’úþØú’’ú(ú½þ^þŸÎÎa¢aÎÎÿ€€$0++"&5#"&54762  >& $$ ^ÀÀÀ ?  @ÒþØú’’ú(ú’’rÎþŸþ^þŸÎÎa¢a”þ ` ? þÀù’úþØú’’ú(ú½þ^þŸÎÎa¢aÎÎ #!.'!!!%#!"&547>3!2ÿ<Ôý<Ô<_@`&ú€&î 5@5 î@ ðþ À¢þ&&â>=(""ýØ=ÿ€€'#"'&5476.  6 $$   ýà !  ’úþØú’’ú(úrÎþŸþ^þŸÎÎa¢a¥JþÀ %€%þÀË(ú’’úþØú’’_þ^þŸÎÎa¢aÎÎÿ€€3#!"'&?&#"3267672#"$&6$3276&þ@*Š”Éh½ŠQQнhwÔI ‰ mþʬœþäÎzzΜ“k‚)'þ@&('ЉQŠ½Ð½ŠQh_  Š „‘zÎ8Îzoeÿ€€$G!"$'"&5463!23267676;2#!"&4?&#"+"&=!2762ç@þhþî’þïk4&&À&‰G´a†èF *À &þ@&ДɆèF *Ç Aš’k‚4&àþôþ³nf&À&&4‰BH‚rdþ@&&4Љ‚rd  Moe&€/?O_o+"&=46;25+"&=46;25+"&=46;2#!"&=463!25#!"&=463!25#!"&=463!24&#!"3!26#!"&5463!2€ @  @  @  @  @  @ € ü@  À  ü@  À  ü@  À € ú@  À €^Bú@B^^BÀB^`@  @ ó@  @ ó@  @ ýó@  @ ó@  @ ó@  @ ý3@  üÀ MûÀB^^B@B^^€€!54&"#!"&546;54 32@–Ô–@8(ü@(88( p (8Àj––jþàýÀ(88(@(8À¸þø¸À8@ÿ€€7+"&5&5462#".#"#"&5476763232>32@@ @ @KjKÀך=}\‹IÀþð&:ì¹kº~&26]S &H&û  ò&H5KKuýt,4,’ &æ x:;*4*&€€K#+"&546;227654$ >3546;2+"&="&/&546$ €<¹‰X@@Gv"D°þ×þ²þ×°D"vG@@X‰¹<†à4L4à†Ц”1!Sk @ G< _b”œœþú”b_ 4.54632&4þ³þú&&M4&€UF &""""& F ûÀ&M&€&M&þ˜ƒ%.D.%ÿ¹€G-Ik"'!"&5463!62#"&54>4.54632#"&54767>4&'&'&54632#"&547>7676'&'.'&54632&4þ³þú&&M4&€UF &""""& FUªŒ &'8JSSJ8'& ŒªþÓ &'.${ŠŠ{$.'& Ó ûÀ&M&€&M&þ˜ƒ%.D.%7þÎþý;&'6£¸£6'&;¶þ4þ[&$ [2[ $&[ €€ #/37#5#5!#5!!!!!!!#5!#5!5##!35!!!€€€€€€ü€€þ€€þ€€þ€ÿý€€€€€€þ€€€€€ý€ý€€ý€€€€€€€€ü€€þ€€ý€ý€€þ€€€€þ€€þ€€€€ý€€ý€€€ #'+/37;?3#3#3#3#3#3#3#3#3#3#3#3#3#3#3#3#3???? ^>>~??????~??~??^??½^^? ^??€úúúúúúúúúúúúúúú€€ÿ•ë€4&"2#"'.5463!2ÀKjKKjv%þ'45%ý5&5L4 5€&Ë% jKKjKþ@5%þ%%Ì%€5 4L5&ý6'ÿ•k€54&"2#"'.5463!2#"&'654'.#32ÀKjKKjv%þ'45%ý5&5L4 5€&Ë%€%þ'4$.Ö%%ý5&€5à5€&Ë% jKKjKþ@5%þ%%Ì%€5 4L5&ý6'45%þ%Ö%54'Ê&55&ý6' ÿ€y€Tdt#!"&'&74676&7>7>76&7>7>76&7>7>76&7>7>63!2#!"3!2676'3!26?6&#!"3!26?6&#!"g(þísAüeM ,*$/ !'& ùJPþî$G]ü› x›6,&ûí `  ý  h `  ý  "9Hüv@WkNC<.  &k& ( "$p" . #u&#  %!' pJüvwEFÛ#  @  þÀ  @  ÿ—€2#"' #"'.546763Œ!''!0#þGþG$/!''!€ 8"ú÷"8  ¨þX! 8" "8 ÿ€€€ <)!!#"&=!4&"27+#!"&=#"&546;463!232€€ü€€ (8ý€€&4&&4¦ à8(ü@(8à qO@8( (`˜(@Oq€€8( ý&4&&4&@þ`  (88(   Oq (8(˜`(ÿqÿ€€!)2"&42#!"&546;7>3!2  Iî©©î©àj––jú€j––jà3e55e3ýgrþùþŽþù`©î©©îI–jü€j––j€j–ˆ1GG1ˆû€rþùþŽÿ€€€ Q37&'&#7676767;"'&#"4?6764/%2"%ÕªI¡M <5ý:YíK5 Íg'9') //8Pp]`O8È:ƒ8 /\þ>KM'Bþå0QÑþ>_’„ûþO 4hÔþ ò7f…:jCR1'  -! räAÑ@   ÿ€€€%e%3267654'&'&#"32654'&#"767676765'&'&'&'&/-72632;2/&+L@ƒª%&):SP§J+B¯²UT«4Nýä-M.   3T|-)JXg+59-,*@?|±Z\2BJI‚RtÅTÖ! RHForB^ ­þòÍ‚ŸpKK ,!zb+üe^  B€ñ”W  S  //rAFt/9)ij‚LU>7H$$ ÿ€€J767676?7>5?5&'&'7327>3"#"'&/&IL( 8  )g ='"B”!F76@% ,=&+ @7$ ~Æ)…J~U%@‹ @,Q5(?‡2&g  9,&ÇkþÉžë-   ÿ€ú€i…;?!6?2&'.'&'&"#"2#"'&#"#&5'56767676'&64&'&'&#"#&'52"/&6;#"&?62+Q6¿‚s×%"* ' Gˆ+"!  1( 8nMH¦X‘0:‹ &n+r  , Ð!~:~!PP!~:~!P5d: +UM6a'˜þ´þ™“.'  -   !& #Àñ¬>q\ 0f!)Vû%¢¢%%¢¢%üÿ†€h„;?!6?2&'.'&'&"#"52#"'&#"#&5'56767676''&'&'&#"#&'5&=!/&4?6!546Q6¿‚s¾>"* ' g®)^!  1( 8nMH¦R—-:‹ &n2í  , á¢%ü%¢¢%%5d: +UM6a'˜4þ™“.'  -    !& #‰(,  0f!)Vúó:~!PP!~:~!PP!€/?%#!"&=463!2#!"&=463!2#!"&=463!2#!"&=463!2&ù€&&€&þ€&û&&&&ú&&&þ€&û€&&€&À€&&€&&f€&&€&&f€&&€&&f€&&€&&€/?%#!"&=463!2#!"&=463!2#!"&=463!2#!"&=463!2&ù€&&€&þ€&ü€&&€&&ú€&&€&þ€&ý€&&€&À€&&€&&f€&&€&&f€&&€&&f€&&€&&€/?%#!"&=463!2#!"&=463!2#!"&=463!2#!"&=463!2&ù€&&€&&û&&&&ú&&&&û€&&€&À€&&€&&f€&&€&&f€&&€&&f€&&€&&€/?%#!"&=463!2#!"&=463!2#!"&=463!2#!"&=463!2&ù€&&€&&ù€&&€&&ù€&&€&&ù€&&€&À€&&€&&f€&&€&&f€&&€&&f€&&€&&€/?O_o%+"&=46;2+"&=46;2+"&=46;2#!"&=463!2+"&=46;2#!"&=463!2#!"&=463!2#!"&=463!2 À  À  À  À  À  À  úÀ  @ ú À  À  úÀ  @  úÀ  @  úÀ  @ àÀ  À sÀ  À sÀ  À üóÀ  À sÀ  À üóÀ  À sÀ  À sÀ  À €/?O#"'&47632#!"&=463!2#!"&=463!2#!"&=463!2#!"&=463!2€  þà   € ù@  À  ûÀ  @  ûÀ  @  ù@  À àýÀ     üóÀ  À sÀ  À sÀ  À sÀ  À €/?O#"&54632 #!"&=463!2#!"&=463!2#!"&=463!2#!"&=463!2` þà     © ù@  À  ûÀ  @  ûÀ  @  ù@  À Î þà  @  þàþ À  À sÀ  À sÀ  À sÀ  À #"'#!"&5463!2632' þm©wý@w©©wÀw©“ ' ûÀ*“¦w©©wÀw©©w¥’ÿ€€€."&462!5 !"3!2654&#!"&5463!2€p pp pú€@ ùÀ  @ “^BùÀB^^B@B^ pp pýÀþ@À@   û@  À  û@B^^BÀB^^ÿ€ëk%!7'34#"3276' !7632k[ë[€v ýâ 6 üÀþ`ë%¦þ`¦$65&ë%[ë[k€ ýâ Êþ`üÀ à5%¦ ¥&&ê'ÿ€€4&"2"&'&54 –Ô––Ô–!þ”?H?þ“!,¨,Ô––Ô–mFüú!&&!FmÔ,þÔÿ€€%" $$ ”ú’’ú”ÎþŸþ^þŸÎÎa¢a`@’úþØú’ñþ^þŸÎÎa¢aÎÎÀ-4'.'&"26% 547>7>2"KjKþÔþXþÔQqYn 243nYqQ€$!+!77!+!$5KKµÔþÔ,Ô‘‚ £‹Ù]""]Ù‹£ ø€9>H7'3&7#!"&5463!2'&#!"3!26=4?6 !762xt˜t` þ¢ ^Q©wüÀw©©w@?6 1üÀB^^B@B^ @(` ý`þà\\þà\P˜`t˜t8`À þ¢ ^ýϾw©©w@w© 1^BüÀB^^B~ @Íþàý` \ \˜P€+Z#!"&5463!12+"3!26=47676#"'&=# #"'.54>;547632€©wüÀw©©wÿ M8 pB^^B@B^íþ€ ' þ½sw- 9*##;Noеj ' €#þýw©©w@w© "^BüÀB^^BÖ  Üþ€*Àƒ‰þ°  "g`„81T`PSA:'À*þ€4€/D#!"&5463!2#"'&#!"3!26=4?632"'&4?62 62€©wüÀw©©w@?6 1 üÀB^^B@B^ @ çüÒBþRnB‡Bn^þÂw©©w@w© 1 ^BüÀB^^Bþ @ ÔüÒ®Bnþù‡nBÿC"&=!32"'&46;!"'&4762!#"&4762+!5462ÿ4&þ€€&ÿ4ÿ&€þ€&4ÿ4&€€&4&€€&4š4ÿ&€þ€&4ÿ4&€€&4&€€&4ÿ4&þ€€&ÿÿ€€6'&'+"&546;267Óý: &€&&€& s ú@ Æ ýZ&&€&&ýZ ÿ€€+6'&''&'+"&546;267667Óý: ý: &€&&€& Æ s ú@ Æ ý: Æ ýZ&&€&&ýZ Æ ý: zÿ€€€6'&''&47667Sý:ý:Æs ú@ Æ ý: Æ4Æ ý: ÿ|„ &546húÐ!!0aý À ý $ÿ€€#!"&5463!2#!"&5463!2&þ&&&ü€&þ&&&@ú€&&€&&ú€&&€&&ÿ€€#!"&5463!2&ú€&&€&@ú€&&€&&ÿ€€&54646&5-ÆÆý:s À ý: Æ ý:4ý: Æ ÿ€€+&5464646;2+"&5&5-ÆÆ&€&&€&ý:s À ý: Æ ý: ¦&&ú€&&¦ ý: Æ ÿ€€&54646;2+"&5-Æ&€&&€&s À ý: ¦&&ú€&&¦  62#!"&!"&5463!2Æ4Æ ú@ Æú€&&€&&-Æý:ýæ&&&ÿ&5ÿ¶ Ë&4762 "æýt%%Œ%k%K%%þæ%%K%k%‹%k%‹%%K%k%þþ&j%K%uÿµKË"/&547 &54?62K%ýt%j%L%%æþ%%L$l$Œ%À4'ýu%%K'45%æå'45%K&&ýu%ÿ€€#/54&#!4&+"!"3!;265!26 $$ À&ÿ&€&ÿ&&&€&&@ÎþŸþ^þŸÎÎa¢a@€&&&ÿ&€&ÿ&&&+þ^þŸÎÎa¢aÎÎÿ€€54&#!"3!26 $$ À&ý&&&@ÎþŸþ^þŸÎÎa¢a@€&&€&&+þ^þŸÎÎa¢aÎÎÿ€€+74/7654/&#"'&#"32?32?6 $$ }µµZµµZµµZµµZƒÎþŸþ^þŸÎÎa¢ažµµZµµZµµZµµZÎþ^þŸÎÎa¢aÎÎÿ€€#4/&"'&"327> $$ [4þhâ4[jüÎþŸþ^þŸÎÎa¢a"ZþiâZþ–Jþ^þŸÎÎa¢aÎÎÿ€€:F%54&+";264.#"32767632;265467>$ $$ €ÀÀo¦Wó€„  5!"40K(0?iÀ+! ":€ÎþŸþ^þŸÎÎa¢a ÀÀ®X–RÕd D4!&.uC$=1/J=þ^þŸÎÎa¢aÎÎÿ€€.:%54&+4&#!";#"3!2654&+";26 $$ `þÀ``À€ÀÀ€ÎþŸþ^þŸÎÎa¢a   þÀ Ž  Áþ^þŸÎÎa¢aÎÎÿ€€/_#"&=46;.'+"&=32+546;2>++"&=.'#"&=46;>7546;232­m&&m ¡l&€&l¡ m&&m ¡l&€&l¡s&%ë¡&€&¡ë%&&%ë¡&€&¡ë%&&€&l¡ m&&m ¡l&€&l¡ m&&m ¡,€&¡ë%&&%ë¡&€&¡ë%&&%ë¡&ÿ€€#/;"/"/&4?'&4?627626.  6 $$ I’  ‰‰  ’ ‰‰ ’  ‰‰  ’ ‰‰ Í’úþØú’’ú(úrÎþŸþ^þŸÎÎa¢aÉ’ ‰‰ ’  ‰‰  ’ ‰‰ ’  ‰‰ (ú’’úþØú’’_þ^þŸÎÎa¢aÎÎÿ€€ , "'&4?6262.  6 $$ “þZ4þÚf4“4fz’úþØú’’ú(úrÎþŸþ^þŸÎÎa¢aÓþZ&4f“f4ú(ú’’úþØú’’_þ^þŸÎÎa¢aÎÎÿ€… "4'32>&#" $&6$  Wý‰ oÉ’Vü󇥔ú’ zÍþãþÈþãÍzzÍ8̓¡†ýYW’˼ò[’ü”¢?þÆþâÎzzÎ:ÎzzÎ@ÿ5K #!#"'&547632!2A4ý@%&&K%54'ýu%%‹&54&K&&þÛÀ4A€€5KþÚ$l$L%%Œ%54'Š&&J&j&þÛKÿ5ÀK #"/&47!"&=463!&4?632À%ýu'43'K&&%ý@4AA4ÀþÛ&&K&45&‹%@6%ýu%%K&j&%K5€5K&$l$K&&ýu#5ÿ€K@!#"'+"&5"/&547632K%K&56$þÚK5€5KþÚ$l$K&&‹#76%‹%53'K&&%ý@4AA4ÀþÛ&&K&45&‹%%ýu'5ÿµK€"#"'&54?63246;2632K%ýu'45%ýu&&J'45%&L4€4L&%54'K%À5%ýt%%Œ$65&K%%þÚÀ4LL4ý@&%%K'ÿ€À,"&5#"#"'.'547!3462þ4&àb›™qb>#  5¢Éà&4š4þ& 6Uu e7D#  "¦Ç†“&þÿ€€/#!"&546262"/"/&47'&463!2ó þ´&þ@&&4L  r&4þ´  r L&À&í þ´4&&À&L rIþ@&þ´ r  L4&& ÿós/"/"/&47'&463!2#!"&546262&4þ´  r L&À&ó þ´&þ@&&4L  r@þ@&þ´ r  L4&&“ þ´4&&À&L r€€##!+"&5!"&=463!46;2!2€8(þ`8(À(8þ`(88( 8(À(8 (8 À(8þ`(88( 8(À(8 (88(þ`8€€#!"&=463!2€8(û@(88(À(8 À(88(À(88zÿ€€5'%+"&5&/&67-.?>46;2%6Ê.@g.þöL4€4Lþö.g@. þö.@g. L4€4L .g@.þöæg.n.™þÍ4LL43™.n.gššg.n.™34LL4þÍ™.n.gšÿ€€ -  $54&+";264'&+";26/¢aÎÎþŸþ^þŸÎβ À  À  Ü ¹€ÎþŸþ^þŸÎÎa¢aûï¾ ¾ fm  ý“ @ J%55!;263'&#"$4&#"32+#!"&5#"&5463!"&46327632#!2 þÀ$À$þ8Ã~+(88Ø8(+}Â(°`8(ûÀ(8`¸]ƒƒ]k=€€=k]ƒƒ]¸´8ÔÀÀþ,8e¡8P88P8¡ þÀþ`(88( @ƒºƒM¥¥Mƒºƒ€O4&#"327>76$32#"'.#"#".'.54>54&'&54>7>7>32&¬þÜãz&^‰¶&.þëÛÖà”Š’/+>*>J> W—¾m7´³²•' '"''? &4&c©‡&^|h_bàþÂml/J@L@ #M6:D 35sÒŸw$ '% ' \„tÿ€3#!"&=463!2'.54>54''€ úÀ  @ ÿ1O``O1CZŒ‰Z71O``O1BZŒ‰Z7 @  @ N„]SHH[3`€)Tt¬bN„]SHH[3^‚)Tt¬€!1&' 547 $4&#"2654632 '&476 €˜å=þùþŽþù=嘅‘Ô‘ýµ}³(zVlŒþ'ýòþ'ŒŒÙÙŒ@ìuhy¹þù¹yhuìÍóó9(³}VzþÒD#æþëå#D#åþêåÿ à =CU%7.5474&#"2654632%#"'&547.'&476!27632#76$7&'7+NWb=嘧‰}³(zV‡iþ\j1  z,ñX™Æ Y[6 $!%ž‚À'F–þuÞJÔiys§?_¯9É?Àkyhuìþþn(³}Vzï¼ý ½YF  KA؉Lëa  þ0‹å2ö-„F"@Q¬¾„î¼³sp@²_ÿ€ð!3%54&+";264'&+";26#!"&'&7>2 À  À  Ü ¹ #%;"ú";%#`,@L¡ € þéþý5 `  ½ü  ` Âþ €™ LÀ`4ÀL¡ýH` üþýÂ`  ü½ a 5 € Ÿ L@ÿ€ #37;?Os!!!!%!!!!%!!!!!!!!%!!4&+";26!!%!!!!74&+";26%#!"&546;546;2!546;232€ þà`@þÀþ  þà`@þÀþ  þàà@þÀþ€@þÀ þàþ€@þÀþ  @  @ à þàþ€@þÀ€ þà  @  @ €L4ú€4LL4€^B@B^€^B@B^€4L€ þà @@þÀ@@ ü À ü @@   þà ü­@@ þà À  þà Mû4LL44L`B^^B``B^^B`Lÿ à7q.+"&=46;2#"&=".'673!54632#"&=!"+"&=46;2>767>3!54632š7>7&54>$32ðþdôFKÆþú1A  0) µŽðL¶ôœ.þ¤þÙ«¯C58.H(Y–‚í¬e«ÿ€€#3C $=463!22>=463!2#!"&5463!2#!"&5463!2Åþ¡þHþ¡Å&€&/7#"&463!2!2€KjKKjËKjKKjË ûì˜&&ü&%±Ì&& ±&5jKKjKKjKKjKÀþ%z 0&4&&3D7&4& %&€€#!"&5463!2!2€„\û@\„„\@\„ \„ ý@\„„\À\„„\ „W€*#!"&547>3!2!"4&5463!2!2Wþ°+›BûÀ"5P+›B@"5þ©üÀ^Î=þ¯„\@\„ \„H#þt3G#Œ3G: _HþtÀ\„„\ „@ÿÀ+32"'&46;#"&4762À&€€&ÿ4ÿ&€€&4Ú4&ü&4ÿ4&&4ÿ@À"&=!"'&4762!5462ÿ4&ü&4ÿ4&&4š4ÿ&€€&4&€€&ÿÿ€€€ /!!!!4&#!"3!26#!"&5463!2ÿ€ÿ€ÿ€ÿ€ ùÀ  @ €^BùÀB^^B@B^þ€€ü€€ÿý€€€üû À  û@ Íû@B^^BÀB^^ÿ€€0@67&#".'&'#"'#"'32>54'6#!"&5463!28ADAE=\W{âO[/5dI kDt‘”®pÄŒe1?*©wü@w©©wÀw©ž (M& B{Wta28r=Ku?RZ^Gw›©T -ü@w©©wÀw©©ÿ€€#7#546;5#"#3!#!"&5463!2Æ8n¯˜„ƒƒ”©wü@w©©wÀw©jÛm1'ÛƒÛý…{öü@w©©wÀw©©ÿ€€#'.>4&#"26546326"&462!5!&  !5!!=!!%#!"&5463!2 B^8(ò–Ô––Ôü–ú€áþÂáá>üá€þ€€üÄ@ý|€K5ú5KK55K²^B(8Ô––Ô–ü€>ááþÂá€þÀvŠ€€û5KK55KKÿH“€G4&"&#"2654'32#".'#"'#"&54$327.54632@p p)*Ppp p)*PÃb '"+`ÜN*(ýa°½£Í¾2 £Íƒc`." b PTY9° ppP*)p ppP*)þb ".`Ü(*NŸƒÍ£ 2¾Í£½°þ`+"' b MRZBÿ€ð½û4&"24&"264&"26#"/+"&/&'#"'&547>7&/.=46?67&'&547>3267676;27632#"&'"'#"'&547&'&=4767&547>32626?2#"&'"'#"'&547&'&=4767&547>32626?2€–Ô––Ô–LhLKjKLhLKjKþ€ › "8w s%( º ")v  > ˜  › "8x s"+ º ")v  < ˜ €• 3zLLz3 •• 3>8L3)x3 •• 3zLLz3 •• 3>8L3)x3 •Ô––Ô–ÿ4LL45KK54LL45KKþ¹ #)0C wZ l/ ™ Y… N,& ¹ #)0C vZl. ™ Y… L0"ýàŒqG^^GqŒq$ ]G)FqðŒqG^^GqŒq$ ]G)Fqÿ€%O#"'#"&'&4>7>7.546$ '&'&'# '32$7>54'€¼þ»¿VZ|š$2 $ |޼E~E<Ž| $ 2$š|ZVþñÉ:¡(t}†–‹þêì‰X(  &%(HÒw‹ì‰‰ý‰xÑH(%& (X„ZT\ð†MKGÖÿ€<m$4&"24&#!4654&#+32;254'>4'654&'>7+"&'&#!"&5463!6767>763232&4&&4¦N2þ `@`%)7&,$)' %/0ÓƒyÀ#5 +€1 &<¬$]`»{tþà5KK5$e:1&+'3T†F0°h˜¦4&&4&€3M:Ë;b^v…+D2 5#$ý€I§IJ 2E=\$YJ!$MCeM‹¡-+(K5€5KƒK5y„*%AŠu]c˜ÿ€=p4&"24&'>54'64&'654&+"+322654&5!267+#"'.'&'&'!"&5463!27>;2&4&&4¦+ 5#bW€ƒÓ0/% ')$,&7)%`@``2N€˜h°0##†T3'"( 0;e$þî5KK5 t€¾ipŒ­<& 1&4&&4&þ#\=E2 JIURIý€$#5 2D+…v^b;Ë:M2g˜c]vDEA%!bSV2MƒK5€5K(,,ž‰MeCM$!Jÿ­@à#"&547&547%6@þ?Vþ”8öáàúÅì ôb% IÇ)ÿ€€94.""'." 67"'.54632>32€+C`\hxeH>Hexh\`C+»ED¼€åý‘4ý #LoP$$Po>àþ¬Q|I.3MCCM3.I|Q¨»ýÐ/¼¨Ýåý¨Z$_dŽCÜø+I@$$@I+ø (@%#!"&5463!2#!"3!:"&5!"&5463!462€ þÀw©©w@  þÀB^^B   ýà4&þ@&&À&4 `  ©wÀw©   ^Bý@B^ 24ýà& &€& &ýàÿ€€%573#7.";2634&#"35#347>32#!"&5463!2íççöFtIG9;HIç’xˆIçç<,tÔ©wü@w©©wÀw©z¶Ö4DD43EEü§ŽšžueBýŒ„&#1sü@w©©wÀw©©ÿ€€ .4&"26#!+"'!"&5463"&463!2#2à &þS3 Lþl&c4LL4€4LL4c Àþ@þ®&þ å&{ÅLhLLhLþÅ'?#!"&5463!2#!"3!26546;2"/"/&47'&463!2€©wüÀw©©wÀý@B^^B@B^@€&4°ýt  r Œ°&&`þÀw©©w@w©@^BüÀB^^B@Rþ&°ýt r  Œ°4&&@"&5!"&5463!462 #!"&54&>3!2654&#!*.54&>3!2 ýà4&þ@&&À&4 s©wþÀ  @B^^Bþà  @w©š4ýà& &€& &ýà3ý@w©   ^BÀB^   ©ÿ€€€ I&5!%5!>732#!"&=4632654&'&'.=463!5463!2!2ÊJÿ½ÃÿJ½€SÍq*5&=CKuüÀuKC=&5*qÍS8( ^B@B^ (8¢Ñ`N¨ö`Ñ¢¨Î€GtO6)"M36J[E@@E[J63M")6OtG€(8`B^^B`8ÿ€€%-3%'&76'&76''&76'&76'&6#5436&76+".=4'>54'6'&&"."&'./"?+"&5463!2Š  2  5    z<: Æ©wà 49[aA)O%-j'&]Æ]5r,%O)@a[9( 0BA; + >HCàw©©wÀw©¸  5 /)  u    ±ü@w©ïa-6OƒUyU[q ( - q[UyU‚P6$C +) (  8&/ &‚©wÀw©©ÿ€€À'?$4&"2$4&"2#!"&5463!3!267!2#!#!"&5!"'&762&4&&4&&4&&4¦8(ú@(88(«c==c«(8þ»*ÿ&ÿ&ÿ*À6À&4&&4&&4&&4& þÀ(88(@(88HH88`(þ@&&À('Àþ@ÿ€ÿ€1d4&'.54654'&#"#"&#"32632327>7#"&#"#"&54654&54>76763232632   N<è;+gC8‰A`1a9á9µgÕw€Œü›|Ê9â8aIe$I€VNšÂz<ç:LQJ  Æ,‹-[% 061Iéï( )W,$-׋¥þ»û7,oIX(¡)oÕζA;=N0 eTZ  (€€O#".'&'&'&'.54767>3232>32€ e^\3@P bM€þïO0# 382W# & 9C9 Lĉ" 82<*9FF(W283 #0O€Mb P@3\^e FF9*<28 "‰ÄL 9C9 & #€€!"3!2654&#!"&5463!2`üÀB^^B@B^^Þ©wüÀw©©w@w©^BüÀB^^B@B^ üÀw©©w@w©©ÿ—€#!72#"' #"'.546763€ü§YY§ !''!0#þGþG$/!''!û&–UUþjZ 8"ú÷"8  ¨þX! 8" "8 ÿ€€EU4'./.#"#".'.'.54>54.'.#"32676#!"&5463!2G55 :8 c7 )1)  05.D <9¤0)$9“©wü@w©©wÀw©W + AB 7c  )$+ -.1 “9$)0¤þÇ< D.59ü@w©©wÀw©©,T1# '327.'327.=.547&54632676TC_L›ÖþÒ¬þñá#+á°i¦!+*p“DNBN,y[ƽ†Œ`m`%i]hbE‚þýî·m‘Š}a ±u&,ŽSXK•³ &$†½f9s? ÿ€ð!#!#3546;#"ÿãþ«ªª¬ÅãŽ'/ÔþäüÈ8«¶»þä "# ÿ§€R&=4'>54'6'&&"."&'./"?'&54$ þÛè49[aA)O%-j'&]Æ]5r,%O)@a[9( 0BA; + >HCèþÛÎa¢a΀ûþoMÓa-6OƒUyU[q ( - q[UyU‚P6$C +) (  8&/ &fM‘ûÑaÎÎþŸ€€%+"&54&"32#!"&5463!54 €&@&–Ô–`(88(ü@(88( rÀÿ&&j––jÀ8(ýÀ(88(@(8À¹þùÿ€€€#'+2#!"&5463"!54&#265!375!35!àB^^BùÀB^^B € ù€ `€€€^Bû@B^^BÀB^€ àà û `ý  €€€€€€€!="&462+"&'&'.=476;+"&'&$'.=476; €p pp p‡$þ»å! $qr‡ % ²þãþ}×#ߺ»Ö pp pþÅ!åE$‡ ‡rqþÜ¢#׃² % Ö»ºþ!)?"&462"&4624&#!"3!26!.#!"#!"&547>3!2/B//B//B//BŸ û@  À û2œüò±^Bû@B^Å\77\ÅaB//B//B//B/ð@  þÀ íâ  ý~þÀB^^B@2^5BB5ý¢2ÿƒ€.42##%&'.67#"&=463! 2€5KK5L4þ_þu:B&1/&¥¬.- zB^^Bà³Í4L€þvþŠy€KjKþ€4L[!^k'!A3;):2*54&#"+323254'>4'654&'!267+#"'&#!"&5463!2>767>32!2&4&&4¦N2ýÀ$YGB (HGEG H¾ÅQ½#5K4L€—i©!<¬…½¤;þà5KK5 A# ("/?&}£vh˜¦4&&4&€3M95S+C=‹,@QQ9ý€@@§IJ 2E=L5i˜>9eM‹¡E;K5€5K J7R>@#†zD<˜ÿ€€7?s%3#".'.'&'&'.#"!"3!32>$4&"2#!"#"&?&547&'#"&5463!&546323!2` #A<(H(GY$ýÀ2NL4K5#aWTƾh&4&&4¦K5þà;¤¾ް=!©i—˜hv£}&?/"( #A  5K€€2*!Q@.'!&=C+S59M34L=E2 JI UR@@&4&&4&€ý€5K;E›ŒLf9>˜ig˜R7J Kÿ5h4&"24#"."&#"4&#"".#"!54>7#!"&54.'&'.5463246326326&4&&4¦§IJ 2E=L43M95S+C=‹,@QQ9€@@€E;K5ý€5K J7R>@#†zD<˜gi˜>9eM‹¡Z4&&4&<½#5K4LN2ýÀ$YGB (HGEG H¾ÅV…½¤;þà5KK5 A# ("/?&}£vh˜—i©!<¬ÿ4<p4.=!32>332653272673264&"2/#"'#"&5#"&54>767>5463!2€@@ý€2*! Q@.'!&=C+S59M34L.9E2 JI UR€&4&&4&›ŒLf6A˜ig˜6Jy‡#@>R7J K5€5K;E@TƾH #A<(H(GY$ýÀ2NL4K#5#a=4&&4&ýDް=©i—˜hv£}&?/"( #A  5KK5þà;¤¾ÿ€€+54&#!764/&"2?64/!26 $$ &þ ½[6þ–[[j6[½ö&ÎþŸþ^þŸÎÎa¢a@€&½4[þ–[6[þ–[6½&+þ^þŸÎÎa¢aÎÎÿ€€+4/&"!"3!277$ $$ [þ–6[½þ &&ö½[6j[ ÎþŸþ^þŸÎÎa¢ae6[j[6½&€&½4[j[þþ^þŸÎÎa¢aÎÎÿ€€+4''&"2?;2652?$ $$ þ–[6[þ–[6½&€&½4[ÎþŸþ^þŸÎÎa¢af6j[[þ–6[½þ &&ö½[ýþ^þŸÎÎa¢aÎÎÿ€€+4/&"4&+"'&"2? $$ [6½&€&½4[j[6[jÎþŸþ^þŸÎÎa¢ad6[½ö&&þ ½[6þ–[[jÿþ^þŸÎÎa¢aÎÎÿ€€ Ø  $2>767676&67>?&'4&'.'.'."#&6'&6&'3.'.&'&'&&'&6'&>567>#7>7636''&'&&'.'"6&'6'..'/"&'&76.'7>767&.'"76.7"7"#76'&'.'2#22676767765'4.6326&'.'&'"'>7>&&'.54>'>7>67&'&#674&7767>&/45'.67>76'27".#6'>776'>7647>?6#76'6&'676'&67.'&'6.'.#&'.&6'&.5/¢aÎÎþŸþ^þŸÎÎD&"      4   $!   #          .0"’Y +  !       $     "  +       ½Î‘      €ÎþŸþ^þŸÎÎa¢aþÅ                        PŽ   ' -( # * $  "  !     * !   (         ü‚$™      2 ÿ~€/$4&"2 #"/&547#"32>32€&4&&4ªýV%54'j&&©'—Ü/ë¹þù¹:,þÛÁ”{ &4&&4&äýV%%l$65&©b—Œ'C†§r! " ©àk[G€ +;%!5!!5!!5!#!"&5463!2#!"&5463!2#!"&5463!2€ý€þ€ü€€þ€&ù€&&€&&ù€&&€&&ù€&&€&€€€€€€ü@ÿ&&&&æÿ&&&&æÿ&&&&ÿ€{#"'&5&763!2{þ' ÿþ**Ù)þý*æí)'/!5!#!"&5!3!26=#!5!463!5463!2!2€þ€^Bú@B^ &@&`ÿù^B`8(@(8`B^€ýþ B^^Bà && €€àþ€€B^ (88( ^ÿ€€G 76#!"'&? #!"&5476 #"'&5463!2 '&763!2#"'þc)'&þ@*þþ*þ@&('cþ (&À*cc*À&' ãþþ*þ@&('cþ'(&À*cc*À&('þc'(&þ@*ÿ€19AS[#"&532327#!"&54>322>32"&462 &6 +&'654'32>32"&462Q¢g†Rp|Kx;CB€’yü–y’ 6Fe= BP†ˆ†PB =eF6 ü–Ô––ÔVáþÂáá>!pR†g¢QBC;xK|€–Ô––Ô€{QNa*+%‹ýx‹‹x5eud_C(+5++5+(C_due2Ô––Ô–þþÂáá>áýŸNQ{u‹%+*jÔ––Ô–ÿpð!Ci4/&#"#".'32?64/&#"327.546326#"/&547'#"/&4?632632°Ð(* 8( !Î)(“ýAÎ('“Ð)* 8( !U“SxySÎSXXVzxTÐTU“SxySÎSXXVzxTÐ@(Ð  (8 *(Ï’è(Ï’'(Ð (8 ýáðS’SUÏSx{VXXTÐTðS’SUÏSx{VXXTЀ€#!"5467&5432632€áŸûÀ¹þùŽt,Ôž;F`j–)¨€Ÿá¹„Û6Ô,°Ž>–jK?Ñsÿ€ €!%#!"&7#"&463!2+!'5#÷8Ejû€jE8÷@&&&&@þìþðÈþð€XYY&4&&4&þqDþS­%þq%ÿ€N\jx†Œ2"&4#"'#"'&7>76326?'&'#"'.'&676326326&'&#"32>'&#"3254?''7¦4&&4&lû€ ýNnbS„‘ˆVZ bR„’SD zz DS’„Rb)+U‰‘„Sbn² €û\.2Q\dJ'.2Q\dJ.Q2.'Jd\Q2.'Jd`!O×`à€ý  `€ýø± €&4&&4þr$#@ƒB10M5TNT{LŽ5T II T5ŽL;l'OT4ŽM01Bƒ@#$Š*„3;$*„3;ý;3„*$;3„*$ : $/é @@þQq`þÀ@˜Šÿ"%3<2#!"&5!"&5467>3!263! !!#!!46!#! (88(ü@(8ýà(8(˜`( (8D<€þÕ+ý€þÕ+Ä<þ€8(þ`(Øþ€8(þ`€8(û@(88( 8( (`˜(8(þ¸(ÕþÕ«þÕþ¤< þ`(8ý€(`üø€þ`(8ý€ÿ„||?%#"'&54632#"'&#"32654'&#"#"'&54632|žu‡dü÷qÜŸžs] = ý¢Ofj’L?R@T?ý»"&š > þf?rRX=Ed—uždsœŸÞqý¢ = _M–jiLü÷?T@R?E& þf > š=XRr?ý»bÿ€€!1E)!34&'.##!"&5#3463!24&+";26#!"&5463!2€ý€€ þç 08(ýÀ(8€€8(@(8þ€ À  À €8(úÀ(88( (`(€þ€€1  þ`(88( û (88(@  þÀ ü`(88(@(8(þè`ÿ€€#!"&5463!2©wü@w©©wÀw©`ü@w©©wÀw©©/%#!"&=463!2#!"&=463!2#!"&=463!2&ú€&&€&&ú€&&€&&ú€&&€&À€&&€&&æ€&&€&&æ€&&€&&ÿÀ@'7G$"&462"&462#!"&=463!2"&462#!"&=463!2#!"&=463!2€p pp pp pp ð û@  À ú€p pp ð û@  À  û@  À Рpp p pp pý À  À ã pp pý À  À óÀ  À ÿ÷<L\l|#"'732654'>75"##5!!&54>54&#"'>3235#!"&=463!2!5346=#'73#!"&=463!2#!"&=463!2}mQjB919+i1$AjM_3<þ–/BB/.#U_:IdDREê û@ À ú€þ±k*Gˆjì û@ À  û@  À TP\BX-@8 C)5˜Xs J@Ÿ$3T4+,:;39SG2S.7<þÁÀ  Àvcc)¢( %Lþlþ}À  ÀóÀ  À ÿ€€5e2#!"&=463%&'&5476!2/&'&#"!#"/&'&=4'&?5732767654'&àù@Ã0†…2uBo  T25XzrDCBBÕEh:%ì›)0%HPIP{rQŒ9f#-+>;I@KM-/Q"€@@@#-a[µ€ $&P{<•8[;:XICC>.ÿ'5oe71#.0(  l0&%,"J&9%$<=DTIÿ€€cs&/6323276727#"327676767654./&'&'737#"'&'&'&54'&54&#!"3!260% <4„"VRt8<@< -#=XYhW8+0$"+dTÍLx-'I&JKkm’§uw<=Vú@À!X@ v 'åþè|N;!/!$8:IœOb“V;C#V  &   ( þ‡ÃmL.A:9 !./KLwPM¼$ú‚@@ €€/?O_oŸ%54&#!"3!2654&#!"3!2654&#!"3!2654&#!"3!2654&#!"3!2654&#!"3!2654&#!"3!2654&#!"3!2654&#!"3!26#!"&5463!2þÀ@þÀ@þÀ@þþÀ@þÀ@þÀ@þþÀ@þÀ@þÀ@€^BúÀB^^B@B^ ÀÀŽÀÀþŽÀÀÀÀþŽÀÀþŽÀÀÀÀþŽÀÀŽÀÀNûÀB^^B@B^^ÿ›€#+3 '$"/&4762%/?/?/?/?¦%kþÛ*úú6Æ6ÆúËbbbb|ÄÄ<<ÄÄ<Þbbbbýžbbbb»%kþÛÕ6úúÆ6Æ‘bbbþü<<ÄÄ<<Äý^bbbbbb@ÿ€M$4&"2!#"4&"2&#"&5!"&5#".54634&>?>;5463!2€LhLLhþÌ€ž à LhLLhL! '–Ô–þ€–Ô–@' !&  Æ? &&LhLLhL€ à ý®hLLhLÀü j––jj––j &@6/" ÆÀ&&ÿ€€J#"'676732>54.#"7>76'&54632#"&7>54&#"&54$ ÎþŸÑok; -j=y¾hwâŽi¶[+PM 3Ñ©—©‰k=J%62>VcÎþÎa¢aQþ^þŸÎ ]G"±'9‰ð–rÈ~:`}†Chž 0=Z—Ù¤ƒªîW=#uY2BrUI1þ^Fk[|éÑaÎÎÿ€€L2#!67673254.#"67676'&54632#"&7>54&#"#"&5463àw©©wý+U ,i<µåF{¶jhµ}Z+OM  2ϧ•§‡jX–Õ¢¨ìW<"uW1AqSH1þbdš©wÀw©ÿ€€"3g!"&'>32 327#".54632%#!654.54>4&'.'37!"463!2!#!!3¦ þ„_™Znh7 1-$ þÛê—gª &ìWa3\@0g]Bj> Ò©wþ,',CMC,.BA.51 ‡‡þKŠÕL¢~Àw©ÿ€ÿ€9&!q[-A"" ""$!'JN±v=C­dy4Shh/`ŠR~†ý w©ITBqIE2;$@;Ft’‘.  @M_~®©w`ÿ€ÿÿ€€-co%4.'&#"32>4.#"326!#!".547>7&54>7#"&54676!#!5!3l $-1!6hpT6Gs~@;k^7x!=kB]f0@\3aWƒµ‡‡GN.BB.!5@@5!Œ˜þô;y{^<% €¢”L@ (•Õ¾‹^lÿ€ÿ€G'!$"" "$8^2"&5!#2!46#!"&5463!2€€r”M* €*M~–~M**M~–~M*j–û€–jj–€–ê&ù&&&€`À‰P%þàæŒ|NN|Œ|NN|þ*–jj–þ–jj–@û€&&€&&@€ "'&463!2þ@4þ@&€Z4þ@À4&@ #!"&4762&ü€&À4ÀZ4&&4Àþ@@€€€ "'&4762€&4þ@À4&@ü€&À4À&€@€ "&5462@þ@4&&4Àš4þ@&€&þ@ÿ€€€ 3!!%!!26#!"&5463!2 `ý€mý€` €^BúÀB^^B@B^€û   `û€Íû@B^^BÀB^^ÿÀ@ "'&463!2#!"&4762þ@4þ@&€&&ü€&À4ÀÚ4þ@À4&Z4&&4Àþ@ÿÀ "'&463!2þ@4þ@&€Ú4þ@À4&@ #!"&4762&ü€&À4ÀZ4&&4Àþ@ÿ€:#!"&5;2>76%6+".'&$'.5463!2^Bú@B^,9j‡9Gv33vG9ªH9+bIþˆ\ A+=66=+A [þª">nSMÀA_:üæB^^B1&öc*/11/*{Þ'VO3þû@/$$/@í*“?Nh^ÿ°l+!+"&5462!4&#"!/!#>32]þ¶_gTRdg¦dþ·QV?U þ·I*Gg?«Ðü!ß2IbbIJaaüÝýÈiwE33ý×ð00 08ãÿ€€4#"$'&6?6332>4.#"#!"&54766$32zÎþ䜬þÊm‰ IÔwh½ŠQQнhb´F‰*þ@&('‚k“œÎþÈþäÎz‘„ Š  _hQŠ½Ð½ŠQGBŠ'(&À*eozÎ(ÿëØq!#"'&547"'#"'&54>7632&4762.547>32#".'632ë%k'45%þ•&+ÿ~(  (þh  &  \(  (˜  &  ~+54'k%5%l%%l$65+~  &  ˜(  (\  &  þh(  (~ÿ+%þ•'ÿ€!)19K4&"24&"26.676&$4&"24&"24&"2#!"'&46$ €KjKKj KjKKj÷e2.e<^PšŠ,bKjKKjýËKjKKj KjKKj‹#ú†#ŽðLlLðŽKjKKjK jKKjKþŸ~-þ‚M7>7&54$ LþhþÑ‚W.˜{+9E=ÌcÑÑQðþdôFKÆþú1A  0) µðœèœ€‹ì‰pËJ2`[Q?l&‹ììÇþ¤þÙ«¯C58.H(Y–®'««ÿ€:d 6?32$64&$ #"'#"&'&4>7>7.546'&'&'# '32$7>54'YþÎþöj`a#",5NK™ ýž~E¼¼þ»¿VZ|š$2 $ |޼: $ 2$š|ZVþñÉ:¡(t}†–Ž€h²fR˜88T h²Ì²è‰ìþêì‰X(  &%(HÒw‹ìûø(%& (X„ZT\ð†MKGÖ{xÑÿ|€!#"'.7#"'&7>3!2%632u ýä  Åþj ÉH«ŒÊû{(e 9 þ1bÿ€€U#!"&546;5!32#!"&546;5!32#!"&546;5463!5#"&5463!2+!2328(þÀ(88(`þ`(88(þÀ(88(`þ`(88(þÀ(88(`L4`(88(@(88(`4L`(8 þÀ(88(@(8ÀÀ8(þÀ(88(@(8ÀÀ8(þÀ(88(@(8À4LÀ8(@(88(þÀ(8ÀL4À8ÿ€€ÀOY"&546226562#"'.#"#"'.'."#"'.'.#"#"&5476$32&"5462€˜Ð˜&4&NdN!>! 1X:Dx+  +wˆw+  +xD:X1 -ÿU¾Œ à¥!ý*,*&4&Äý¼h˜˜h&&2NN2D &  ..J< $$ 767#"&'"&547&547&547.'&54>2àl4  2cK Eo‡Š‡oED ) € ä € ) D€g-;</- ?.P^P.? -/<;-gY‘·¾·‘YÀ  .2 L4H|O--O|HeO , ™‘‘™ , Oe›q1Ls26%%4.2,44,2.4%%62sL1q›c«qAAq«ÿ à4#!#"'&547632!2#"&=!"&=463!54632 ú  þÁ @  `  þÀ  ú   ` ?`À À  @  @  À! þÀ  À À À þÁ€€54&+4&+"#"276#!"5467&5432632à À à  `  _ €áŸûÀ¹þùŒv,Ôœ;G_j–)‚§``  þ   þ  _ ԟṂÜ7 Ô,®>–jL>Ñ€€54'&";;265326#!"5467&5432632 þ   þ¡ à À à €áŸûÀ¹þùŒv,Ôœ;G_j–)‚§  ` þ¡ þ   `þíŸá¹‚Ü7 Ô,®>–jL>Ñÿ€€€X`$"&462#!"&54>72654&'547 7"2654'54622654'54&'46.' &6 €&4&&4&’yü–y’ %:hD:Fp pG9„F„j– 8P8 LhL 8P8 E; Dh:% þÀáþÂáá>Ú4&&4&}yŠŠyD~–s[4DËd=PppP=dË>hh>@–jY*(88(*Y4LL4Y*(88(*YDw" A4*[s–~ØþÂáá>áÿ€€€M4&"27 $=.54632>32#"' 65#"&4632632 65.5462&4&&4¦G9þùþŽþù¤Ü& <#5KK5!¼¼!5KK5#< &ܤ¼¼9Gp p&4&&4&@>bþuŸáោØ&$KjKþnj––j’KjK$&þØ„j––j‹b>Pppÿ€€ %!5!#"&5463!!35463!2+32€þþ @\„„\ ü€8(@(8„\@@\„€€€û„\@\„û (88( àüÀ\„„ÿ€ -4#"&54"3#!"&5!"&56467&5462P;U gI@L4þ@–Ô–þ@4L¾ÂÀ¨8P8¨À° U;Ig04Lj––jL4¡Ù¥Â(88(Â¥þúþ'ÿ€@"4&+32!#!"&+#!"&5463!2€pP@@Pùð–jûj–@áŸ@„\ý@\„&€Ÿ0 pþ€ýÀj–– þÂá \„„\à&ÿ€-B+"&5.5462265462265462+"&5#"&5463!2€G9L4€4L9G&4&&4&&4&&4&&4&L4€4Là ¼„&Àý€=düõ4LL4 d=€&&þ`&& &&þ`&& &&ùÀ4LL4  „¼&ÿ€€(/C#!"&=463!25#!"&=463!2!!"&5!!&'&'#!"&5463!2ý@Àý@Àü€þ`(8þ€x þÇ 8(ûÀ(88(€(`8(`@@ò@@ý’8( þ€ 9 þhü€(88(@(8(þÈ`ÿ€/?O_oŸ¯¿Ïßïÿ-=%+"&=46;25+"&=46;2+"&=46;2%+"&=46;2+"&=46;2%+"&=46;2%+"&=46;2%+"&=46;2+"&=46;2%+"&=46;2%+"&=46;2%+"&=46;2+"&=46;2%+"&=46;2%+"&=46;2+"&=46;2%+"&=46;2+"&=46;2!!!5463!2#!"&5463!2€ @  @  @  @  @  @ ÿ @  @  @  @ ÿ @  @ ÿ @  @ ÿ @  @  @  @ ÿ @  @ ÿ @  @ ÿ @  @  @  @ ÿ @  @ ÿ @  @  @  @ ÿ @  @  @  @ ÿ€û€€ @ &û&&&à@  @ ó@  @  @  @ ó@  @ ýó@  @ ó@  @ ó@  @ ó@  @ ýó@  @ ó@  @ ó@  @ ó@  @ ýó@  @ ó@  @ ó@  @ þó@  @ ó@  @  @  @ ú“úà  `ù€&&€&& ÿ€/?O_oŸ·Ûõ%+"&=46;25+"&=46;2+"&=46;2%+"&=46;2+"&=46;2%+"&=46;2%+"&=46;2+"&=46;2%+"&=46;2+"&=46;2!!#!"&=!!5463!24&+"#54&+";26=3;26%#!"&5463!463!2!2€ @  @  @  @  @  @ ÿ @  @  @  @ ÿ @  @ ÿ @  @  @  @ ÿ @  @  @  @ ÿ€ÿ8(þ@(8ÿ€ @  @ € @  @ € @ &û&&@8(À(8@&à@  @ ó@  @  @  @ ó@  @ ýó@  @ ó@  @ ó@  @ þó@  @ ó@  @  @  @ ü“€ (88( û€à  À@  ``  þÀ  `` -û&&& (88(þà&@ÿ€€€<c$4&"2!#4&"254&+54&+"#";;26=326+"&5!"&5#"&46346?>;463!2€KjKKjþË€žÃKjKKjËàÀààÀà&À–Ô–þ€–Ô–€&&Æ@ &€&KjKKjK€à ý­jKKjK ÀààÀàà.û€&j––jj––j&4& @Æ@&&ÿ€€#'1?I54&+54&+"#";;26=326!5!#"&5463!!35463!2+32àÀààÀàý€þþ€ \„„\ÀûÀ 8(@(8„\ \„ ÀààÀààû„\@\„û (88( àüÀ\„„€€: #32+53##'53535'575#5#5733#5;2+3€þáþ à@þÛE&&` @@ À` €ÀÀ€ `À @@ `&&E%@à`@ @ @þ    à À € À à   þ @ :#@€€!3!57#"&5'7!7!€ÿK5€û€€€Ÿá@ à À @€€ÿ5Kþ@ÀÀÀáŸ@@€€À üàÿ€€#3%4&+"!4&+";265!;26#!"&5463!2&€&þ&€&&€&&€&©wü@w©©wÀw©À€&&þÀ@&&ü€&&@þÀ&&ºü@w©©wÀw©©ÿ€€#354&#!4&+"!"3!;265!26#!"&5463!2&þÀ&€&þÀ&&@&€&@&©wü@w©©wÀw©@€&@&&þÀ&€&þÀ&&@&:ü@w©©wÀw©©-Mó3)$"'&4762 "'&4762 s 2  þ. Ò  2 þw‰Š 2  þ. Ò  2 þw‰­ 2 Ò  Ò 2  þwþw  2 Ò  Ò 2  þwþw MÓ3)"/&47 &4?62"/&47 &4?62S þ.  2 ‰þw 2  ÒŠ þ.  2 ‰þw 2  ÒM þ. 2  ‰‰  2 þ.  þ. 2  ‰‰  2 þ.M3S)$"' "/&4762"' "/&47623 2  þwþw  2 Ò  Ò 2  þwþw  2 Ò  Òí 2 ‰þw 2  Ò þ.v 2 ‰þw 2  Ò þ.M­3s)"'&4?62 62"'&4?62 623 þ.  þ. 2  ‰‰  2 þ.  þ. 2  ‰‰  2­ þ. Ò  2 þw‰ 2v þ. Ò  2 þw‰ 2-Ms3 "'&4762s þw‰ 2  þ. Ò  2í þwþw  2 Ò  Ò 2 MS3"/&47 &4?62S þ.  2 ‰þw 2  ÒM þ. 2  ‰‰  2 þ.M 3S"' "/&47623 2  þwþw  2 Ò  Òm 2 ‰þw 2  Ò þ.M-3s"'&4?62 623 þ.  þ. 2  ‰‰  2- þ. Ò  2 þw‰ 2ÿ€€/4&#!"3!26#!#!"&54>5!"&5463!2 ùÀ  @ €^Býà &þ& ýàB^^B@B^ @  üÀ MûÀB^%Q= &&& $$ ”þØú’’ú(ú’’rÎþŸþ^þŸÎÎa¢a ’úþØú’’ú(ú½þ^þŸÎÎa¢aÎ΀€!C#!"&54>;2+";2#!"&54>;2+";2pPþ€PpQнh@&&@j–8(àPp€pPþ€PpQнh@&&@j–8(àPp@þ€PppPÀh½ŠQ&€&–j (8pPþ€PppPÀh½ŠQ&€&–j (8p€€!C+"&=46;26=4&+"&5463!2+"&=46;26=4&+"&5463!2Qнh@&&@j–8(àPppP€Pp€Qнh@&&@j–8(àPppP€PpÀý@h½ŠQ&€&–j (8pP€PppPý@h½ŠQ&€&–j (8pP€Pppÿ€À !)19A$#"&4632"&462"&462"&462"&462$"&462"&462"&462ðU;bq™›bà&4þ4&àÉ¢5 ¦þã"  #D7e uU6 ÿ&4&ÿþm†ÿ€€ 1X".4>2".4>24&#""'&#";2>#".'&547&5472632>3€=T==T=™=T==T=¹Šv)šG¬G˜+vŠ@b’†R¨R†’b@à=&‡“Á–\N€§Šˆj!>ˆ3l¤k“¢”„i¤k3ˆhPTDDTPTDDTPTDDTPTDD|x¨ ¨xXƒK--KƒÏ|Mp<# )>dA{ÐíŸRXtfOT# RNftWQ €€,%4&#!"&=4&#!"3!26#!"&5463!2!28(ý@(88(þÀ(88(À(8€„\û@\„„\@\„ \„àÀ(88(@(88(ü@(88èý@\„„\À\„„\ „u€'E4#!"3!2676%!54&#!"&=4&#!">#!"&5463!2!232õ5ûÀ([þÚ5@(\&û‹8(ýÀ(88(þÀ(8,9.þÙ+’CûÀ\„„\@\„ \„À6Z]#+þ•#,k´ (88(@(88(ü«;5E£>:þ•5E„\À\„„\ „\ 1. ÿ€€$4@"&'&676267>"&462"&462.  > $$ n%ÊþÊ%/‡¨‡02þ KjKKjKKjKKjKf«íþüí«ff«íí«æÎþŸþ^þŸÎÎa¢aÍy””y/PccP/ÏjKKjKKjKKjKýþí«ff«íþüí«ff«@þ^þŸÎÎa¢aÎÎÿ€€$4@&'."'.7>2"&462"&462.  > $$ n20‡¨‡/%ÊþÊþ7KjKKjKKjKKjKf«íþüí«ff«íí«æÎþŸþ^þŸÎÎa¢a3/PccP/y”” jKKjKKjKKjKýþí«ff«íþüí«ff«@þ^þŸÎÎa¢aÎÎÿ€€ +7#!"&463!2"&462"&462.  > $$ €&ý€&&€þ&KjKKjKKjKKjKf«íþüí«ff«íí«æÎþŸþ^þŸÎÎa¢aÚ4&&4&µjKKjKKjKKjKýþí«ff«íþüí«ff«@þ^þŸÎÎa¢aÎ΀#+3C54&+54&+"#";;26=3264&"24&"2$#"'##"3!2@À€ÀÀ€À@KjKKjKKjKKjKþÔÔÀ’Ü’ÀÔþÔ,Ô€ÔÀ€ÀÀ€ÀÀgjKKjKKjKKjKÔþXþÔ€€,¨,€€ #/;GS_kwƒŸ£³+"=4;27+"=4;2'+"=4;2#!"=43!2%+"=4;2'+"=4;2+"=4;2'+"=4;2+"=4;2+"=4;2+"=4;2+"=4;2+"=4;54;2!#!"&5463!2€``€àà€``ü `ý€``€``€``€``€``€``þ````àp`€ù€K5ù€5KK5€5Kp``ð``ð``ýð``ð``ð``þð``ð``þð``þð``ð````þ `ðý€ü€€ü€5KK5€5KK@ÿ€€*V#"'.#"63232+"&5.5462#"/.#"#"'&547>32327676€©‰R?d¨^­æõ¼7ac77,9xûm#@#KjKÀ# Ú—XF@Fp:fþõ_ #W¤IpÂp&3z¼ ëh[ 17ý©q%q#:ûò:#5KKuý't#!X: %æ#+=&>7p @ÿ€€ *2Fr56565'5&'. #"32325#"'+"&5.5462#"/.#"#"'&547>32327676@µËͳ¬Ô×éë•8 2.,#,fµk*1x­©‰-!”û¬#@#KjKÀ# Ú—XF@Fp:fþõ_ #W¤IpÂp&3z¼ Àe¹`°Åv½oþ8¸t-à  Þ:5 ¼½[Ä*î#:ûò:#5KKuý't#!X: %æ#+=&>7p  €3$ "/&47 &4?62#!"&=463!2Iþ.  2 ‰þw 2  Ò -ü@À)þ. 2  ‰‰  2 þ. þ-@@-ÿ“Sí$9%"'&4762  /.7> "/&47 &4?62i2  þ. Ò  2 þw‰ Eþ‹ > u > þ.  2 ‰þw 2  Ò ‰2 Ò  Ò 2  þwþw !úõ   ýhþ. 2  ‰‰  2 þ. ÿ€»;#"'&476#"'&7'.'#"'&476€' þ)'þs "+5+•@Õ¡' þ)'›¼©ÆF*4*Eþr4þM:—}}8 ¥GO û*4*þúÁ­ÿ­~à (-/' #"'%#"&7&67%632¢þœBŸ;>< õþ•Vþ?þ?Vþ” -öááö-Cú4 <Bü=¨cB5þžþ !% ìì %!ôb 7IÇ))þ9I7ÿ€€ #"'.5!".67632yý€( ýÀ#  £û##@,( €)ÿ€€8! !++"&=!"&5#"&=46;546;2!76232-Sý€Sý­€àÀü ààÀSö  ÷àSýÚSý`Ààà`Ààà÷  öü­ÿ€€K$4&"24&"24&"27"&5467.546267>5.5462 8P88P88P88P¸8P88P˜4,àD‡€S,4p p4,,4p p4,6d7AL*',4p pP88P8¸P88P8HP88P8`4Yþá&+(>EY4PppP4Y4Y4PppP4Yþ%*54&#"#"/.7!2Àðð<'G,')7ð‚N;2]=A+#H  ¤  0P¢‚RððH6^;<T%-S“#:/*@Z}   >h—€€.%#!"&=46;#"&=463!232#!"&=463!2€&þ&&@@&&€&@&€&ÿ&&&À€&&€&€&€&&ýÀ&fÀ&&À&&b€#!"&=463!2#!"&'&63!2&ÿ&&&'ÿ'%@% à&&à&&ý&&&&þk"G%#/&'#!53#5!36?!#!'&54>54&#"'6763235øŸ ›þþ€Å¹‰‹Œ}¸Ìêýþ4NZN4;)3.i%Sinˆ1KXL7è§§ü* ú§#¨ä& *ä¨þõþاÎ@jC?.>!&1' \%Awc8^;:+54&#"'6763235øŸ ›þþ€Å¹‰‹Œ}¸Ììýþ4NZN4;)3.i%PlnˆEcdJè§§ü* ú§#¨ä& *ä¨þõþØÙÎ-@jC?.>!&1' \%AwcBiC:D'P%! #!"&'&6763!2€Pýþ°õ ü€&:ý&? €&:&?€€þ€5"Kü,)""K,)ÿÜ€h#".#""#"&54>54&#"#"'./"'"5327654.54632326732>32€YO)I-D%n  "h.=T#)#lQTv%.%P_– % %–_P%.%vUPl#)#T=@è/#,-91P+R[¶Ql#)#|'˜' 59%D-I)OY[R+P19-,##,-91P+R[YO)I-D%95%–_P%.%vÿ€€'3!2#!"&463!5&=462 =462 &546 €þÙÙ&&ý€&&ÙþÙ&4&r&4&ÿ¼þø¼¼¼@€Ýþ¹„&4&&4&„GÝ€&&€¹þù¹€&&fþ„¼¼„„¼¼ ÿ€s CK&=462 #"'32=462!2#!"&463!5&'"/&4762%4632e*&4&iþ—¼„76`al¹&4&þÙÙ&&ý€&&}nþ  R Ò  R þzý“¼„f¥Oego€&&€5þ—€„¼`3¹€&&€Ýþ¹„&4&&4&„ Dþ R  Ò R zý“„¼vÿ€€"!676"'.5463!2@þ@w^ëÀCc‰t~5  5~t‰cC&€&@€û?J¸°ýV©ƒ|RIIR|ƒ©V&&ÿ€#G!!%4&+";26%4&+";26%#!"&546;546;2!546;232€€ú€€@@@@€L4ú€4LL4€^B@B^€^B@B^€4L€À þà þàNû4LL44L`B^^B``B^^B`Lÿ€€àL4&"2%#"'%.5!#!"&54675#"#"'.7>7&5462!467%632&4&&4¦  þ@ ÿo‘&þ&}c ;pG=(  8Ai8^„^. À  &4&&4&`þÀ ` f°süà&& j©o/;J!# 2 KAE*,B^^B! ` $ÿ €€-4&"2#"/&7#"/&767%676$!2 8P88P—²Qrþ€ @ Uþçþì @ à {`P¼TP88P8€ùþ•³P`þ… à @U @€rQ»ŽÑ!6'&+!!!!2Ѥþ²² 8©Ìþ²ÌþâÌþ²Ì™üe±;<*ûý@8 !üG¹üG¹GQII¿ÿ€€ %764' 64/&"2 $$ fþÍ3f4þ:Æ4†ÎþŸþ^þŸÎÎa¢af4334fþ:4þ:×þ^þŸÎÎa¢aÎÎÿ€€ %64'&" 2 $$ ÍÆþ:4f3þÍf4FÎþŸþ^þŸÎÎa¢aÆ4Æf4þÍþÍ4f×þ^þŸÎÎa¢aÎÎÿ€€ 764'&"27 2 $$ fþ:4þ:f4334†ÎþŸþ^þŸÎÎa¢af4Æþ:4f3þÍ×þ^þŸÎÎa¢aÎÎÿ€€ %64/&" &"2 $$ -Æf4þÍþÍ4fÆ4æÎþŸþ^þŸÎÎa¢aíÆ4fþÍ3f4þ:wþ^þŸÎÎa¢aÎÎÿ@€€7!!/#35%!'!%jüŒ/dÅÄ ¯jg2ý|þ8€€ý¾ý«¯ýêä55Œþêdc µÕúb¢¢ ÿ@ô€! !%!!7!áþöüÜýFG)¦æDûH:¹&ûH€úËþõ d“¡¡S)¿ÿU4&"2#"/ $'#"'&5463!2#"&=46;5.546232+>7'&763!2À&4&&4f ]wþqþ4þqw] `dCõ•À&&À:F–Ô–F:À&&À•õCd`æ4&&4&ü þ  ]§§] `d[}‡&€&£"uFj––jFu"£&€&ýy}[d€#2#!"&546;4 +"&54&" (88(ü@(88( r&@&–Ô–8(ýÀ(88(@(8@¹þù¹&&j––jþÀÿ€€'3"&462&    .  > $$ –Ô––ÔáþÂáá>aþÔþXþÔ,¨¬f«íþüí«ff«íí«æÎþŸþ^þŸÎÎa¢aêÔ––Ô–þa>ááþÂáTþXþÔ,¨,ý~í«ff«íþüí«ff«@þ^þŸÎÎa¢aÎ΀€/+"&=46;2+"&=46;2+"&=46;2€8(À(88(À(88(À(88(À(88(À(88(À(8 À(88(À(88(À(88(À(88(À(88(À(88€€/+"&=46;2+"&=46;2+"&=46;2€8(À(88(À(88(À(88(À(88(À(88(À(8 À(88(À(88ØÀ(88(À(88ØÀ(88(À(88ÿ€€5E$4&"2%&'&;26%&.$'&;276#!"&5463!2KjKKjª þ¸è šÜ  € f±éþáš  Ì\Ñ € ©wü@w©©wÀw©ËjKKjK"èH  €  Üš  šé±f € Ñþ¤Ì  Íü@w©©wÀw©©ÿ€€   $64'&327/¢aÎÎþŸþ^þŸÎβ ýà! €ÎþŸþ^þŸÎÎa¢aý—J@%ý€% 6ÿ5ËÊ/ 64'&"2 "/64&"'&476227<ýÄþÄijþ–6ý–j6‹üu%k%~8p 8}%%‹%k%}8p 8~%<þÄýÄ<þij4jý–4þ–üt%%~8 p8~%k%Š%%}8 p8}%kÿ€€54&#!"3!26#!"&5463!2&ü€&&€&©wü@w©©wÀw©@€&&€&&:ü@w©©wÀw©©€€/#!"&=463!24&#!"3!26#!"&5463!2€üÀ@€^BüÀB^^B@B^€©wüÀw©©w@w©à@@þ2@B^^BüÀB^^‚üÀw©©w@w©©ú+#!"'&?63!#"'&762ú(Àý@   @À(@>@¥%ü À €%%€þ€ ÿ€ú!232"'&76;!"/&76 À À($þÀ>þÀ(ÀþÀ   ü¡J þ€€&%€ Àÿ€€$%64/&"'&"2#!"&5463!2­ff4þ-Ó4ff4f©wü@w©©wÀw©íf4fþ-Óf4þš†ü@w©©wÀw©©ÿ€€/#5#5'&76 764/&"%#!"&5463!2”˜48`ÒþÝ #þû þàýà€\˜P\ ©wü@w©©wÀw©¬˜4`8º þÝ #ý@  ýàþà`\P˜\`ü@w©©wÀw©©ÿ€€)4&#!"273276#!"&5463!2&þ *ýêf4 '©wü@w©©wÀw©`à&')ýê4f*ü@w©©wÀw©©ÿ€€%5 64'&"3276'7>332#!"&5463!2í`þ '(wƒa8! § ,j.¨Œ( &©wü@w©©wÀw©³`4`* '?_`ze<µß  bw4/ *Àü@w©©wÀw©©ÿ€€-.  6 $$ €ÿ€þ ’úþØú’’ú(úrÎþŸþ^þŸÎÎa¢aÀ€€OýâÿþÝ(ú’’úþØú’’_þ^þŸÎÎa¢aÎÎÿ€€ -"'&763!24&#!"3!26#!"&5463!2yþÀBþÀ(€(˜ ü@  À ©wü@w©©wÀw©]#þ@À##ý À  ü@ Íü@w©©wÀw©©ÿ€€ -#!"'&7624&#!"3!26#!"&5463!2y(ý€(@B@u ü@  À ©wü@w©©wÀw©£###Àþ@þÚÀ  ü@ Íü@w©©wÀw©©ÿ€€ -'&54764&#!"3!26#!"&5463!2@þ@####ÀÛü@À©wü@w©©wÀw©¡BþÀ(€(þÀýìÀü@Îü@w©©wÀw©©ó€`%#"'#"&=46;&7#"&=46;632/.#"!2#!!2#!32>?6Ð#  !"'êþ¢?_  BCbCaàf\ + ~È2Ô þË  þ}0Ë$ åŸ Ý q 90rÒ Ÿ €p r%D p u‰ü€?#!"&=46;#"&=46;54632'.#"!2#!!546;2üüD a__÷¿¹– g *`-Uh1  þÏž¢þ‘–  ƒß«Þ}   $^L׃ þ…µ 4ÿÒb+"&=.'&?676032654.'.5467546;2'.#"ÒÇŸ‡ B{PDg q‚%%Q{%P46'-N/B).Ä ‡9kC< Q 7>W*_x*%K./58`7E%_™Ý¯ ¯ ,-3‡  cVO2")#,)9;J)ŠÐ´ °"!*’ #VD,'#/&>AX‚€>++"''&=46;267!"&=463!&+"&=463!2+32‚¨Ôª§$ à þÎÀ  p„¡þU9Ó‘ @é/«*f´²þš oÌ  VRfq …f=Sÿ€E!#"&5!"&=463!5!"&=46;&76;2>76;232#!!2#![¬ þà   þà  Öþ¿  ×% )¿¿ þÇ×  þÞ"  þÞJg Uh BþW&WX¤ý½ hU gþ¶ €84&#!!2#!!2#!+"&=#"&=46;5#"&=46;463!2‚jþÀ@joýÈþ¬ùþ §ààààÈgÈ|þ@¡þ~ôv€ÀÀ€v• u€ n#467!!3'##467!++"'#+"&'#"&=46;'#"&=46;&76;2!6;2!6;232+32QŸKt#þÜ ¡‹#FŸN¢Qo!þ×"€Õ¤Ÿ¦Ñ§Ÿ  Ð¯!ŽmY ‰Zga~bm]‰ [o‘"³U+þÔ¬€€€ýÔ,þÕ­€€ @ý˜hý˜ h@€@X þ˜hþ˜h þ¨@€8ÿè€3H\#5"'#"&+73273&#&+5275363534."#22>4.#2>•ut 3NtRšP*šHÈo2 LoÔ@!šR(šOzh=Ñ,GID2Fýž þÁ þÀÀÀÀî8PuE>.'%&TeQ,j†m{¤þ+§>RÀ{ß?jJrL6V þÁ @`ú 7>wmR1q uWei’½/rr° :V¹ýr"ÿÎ $7V4&#"326#"'&76;46;232!5346=#'73#"'&'73267##"&54632BX;4>ID2Fýž þÁ þÀÀÀÀÐþ+§>RÀ{Ã8PuE>.'%&TeQ,j†m{¤ß?jJrL6ûª þÁ @`ú ürr° :V¹ýr3>wmR1q uWei’½ÿ€@€ \%4&#"326#!"&5463!2+".'&'.5467>767>7>7632!2&%%& &þà&& & 7.' :@…$LBœWM{#&$h1D!  .I/! NrÀ&&%%ý€&&€&&V?, L=8=9%pEL+%%r@W!<%*',<2(<&L,"rÿ@ \#"&546324&#!"3!26%#!#"'.'.'&'.'.546767>;&%%& &þà&& &i7qNþë !/I.  !D1h$&#{MWœBL$…@: '.À&&%%ýå€&&ý€&&¯=XNr%(M&<(2<,'*%<!W@r%%+LEp%9=8=L ÿ€€ +=\dŒž²Â%54#"327354"%###5#5#"'&53327#"'#3632#"'&=4762#3274645"=424'.'&!  7>76#'#3%54'&#"32763##"'&5#327#!"&5463!2—¸BBýÅPJN±C'%! B? )#!CC $) û 54f…"þ@@ B+ˆþìþíˆ,A  A+‰&‰+A ý ZK35N # J!1331µCCC $)÷©wü@w©©wÀw©é2à«"33èFþY§F~þ‘(-&"þòo’4*)$í¡(*¶ (&;;&&:LA3  8œ33œ4ý±S,;;,W­°T+<<+T;(ÃÃ\g7Éx‚:&&:‚:&&<rþåþÛ%-ü@w©©wÀw©© ÿå +=[c}‰›¯#"'632#542%35!33!3##"'&5#327%54'&#"5#353276%5##"=354'&#"32767654"2 '.'&547>76 3#&'&'3#"'&=47632%#5#"'&53327Ë''RZZü:kþÈid YYY .06­ 62+YY-06 R[!.³'CD''EH$ý VVÏX:¸ý¸:Y X;·æ¸:Y üfyd/%jG¶%EC&&CE%O[52. [$ÓC-D..D–^^ýÇîþ†* lþy1%=^ÅI86Ùýi077S 3 $EWgO%33%O­O%35 ÂÒEEÒFýWêt;PP;pîêt;PP;pþqþñJŠgTþùF¯Q%33&P¯P%33%Rþ 7>%3Šþ‘!+}ÿ€{ö'+"&72'&76;2+"'66;2U ÷&ï ý¡ ï(Ê ýðP ï*þ­'ñeþJ."À-düZý™-n Ž-ÿ€€'74'&+";27&+";276'56#!"&5463!2­~¸}Ä ¹7»þe ¸ þü™Û©wü@w©©wÀw©Ý" Øþ¦ $Q #ý'þ!# ÜÓˆü@w©©wÀw©©/4'&327$ '.'.4>7>76 þ"!!jGÞü~ÞGkjGÞ‚ÞGk[J@&ý€& @–Àl¥AIddIA¥lÀl¥AIddIA¥@ÿ€ÀŠ '5557 ’îþªþ,þþ“VWýQVþþ®.Rþþ©Wéþ®þ=þÏþã?þälþÛ%l`þäØþãþÐþòþñþÁ~þÁþò0ÿ~#%5!'#3! %% % ý=´û”#y üØÀ ý?R«'ýUÊaMýŸµŽ|þqBy•y‡——[ýC#àý–jXA–AÒ·’·ïþ˜‚hÍý·UHéýG¹ÿ€€/?%##"547#3!264&#"3254&+";267#!"&5463!2R‡€Ü‚Åþè#-$þäµ€µµ€Ñ(®((®(®tQûŠQttQvQtnˆ?D~Õ|ÀD?ýx##³ø¯¯ø¯“¥))¥((íûŠQttQvQttÿ€€2#!"&54634&"2$4&"2àw©©wü@w©©wš|°||°°|°||°€©wü@w©©wÀw©ü¨°||°||°||°|ÿ€€ !3 37! $$ Éþn6^þ5þ5^h ûÎþŸþ^þŸÎÎa¢a’þÎà³ýM 1þ^þŸÎÎa¢aÎÎÿP£ *Cg'.676.7>.'$7>&'.'&'? 7%&'.'.'>767$/u5'&$I7oÆb?K“\[zäH,1þÝþí+.@\7<äÜ?5\V ,$VÏÅg.GR@ ß7àµU,+!üþšø’  # "8$}¼{)›<¥?L RR ;kr,yE[€˜z# /1 "# #üeCI0/"5#`Ä ””"8¸§þ4~&p )4 2È{¬H- .%W.L>ÿ€€':Yi4&67&'&676'.'>7646&' '7>6'&'&7>7#!"&5463!2PR$++'TJX„j7-F¶C',›©,&C ."ÆÒ!$28 ¡þh¢ /ù³"‡ +pØþñ„^&+3$ i³µ0(©wü@w©©wÀw©š+.i6=Bn \C1XR:#"ý'jj š8Q.cAjÇ57!? "0DŒÊ$4" P[ & 2ü@w©©wÀw©©Nÿ€€#3!!327#"'&'&'&5#567676†Ûlþ” '2CusfLM`iQN<:ª[@@''€þ|ñþvˆ$%Lò02366kÙ67MNÿ€€#3%5#"'&'&5!5!#33276#!"&5463!2cXV3% þî¤ 10D*+=>NC>9ê©wü@w©©wÀw©µ8c'µ#Z99*(£þlN+*$% ü@w©©wÀw©©ÿ@ý#"'&76;46;23õ þ¢  þ  àÀà&þ€ €àû ÿýÀ++"&5#"&7632ý àÀà ^  c û à&€ þ€@ý#!'&5476!2û &þ€ €ààÀà ^  b àÀý'&=!"&=463!546À þ€û à&€ ƒ þž àÀà þ¢ ÿ€q&8#"'&#"#"5476323276326767q'T€1[VA=QQ3˜•“qp¬Hih"-bfGw^44O#AŠþá?66%CKJ°A}}Ä !"òä’""A$@C3^q|Æz=KK?6 •lk) ÿ€€ %!%!ªýVªýV€üu‹üuýu^-çým5ýwüî}•nüæÿ€~7M[264&"264&"2"&546+"&=##"&5'#"&5!467'&766276#"&54632Ý  ¼  üû*<;V<<O@-K<&4'>&4.'.'.'.'.'&6&'.'.6767645.'#.'6&'&7676"&'&627>76'&7>'&'&'&'&766'.7>7676>76&6763>6&'&232.'.6'4.?4.'&#>7626'.'&#"'.'.'&676.67>7>5'&7>.'&'&'&7>7>767&'&67636'.'&67>7>.'.67— \ þ›U7  J#!W! '  " ';%  k )"    '   /7*   I ,6 *&"!   O6* O $.(¨ *.'  .x…,  $CNý¡    £  * ´ 8   7%&&_f& ",VL,G$3¤@@$+ "  V5 3"  ""#dA++ y0D- %&n 4P'A5j$9E#"c7Y 6" & 8Z(;=I50 ' !!e  þR  þš "+0n?¢t(-z.'< >R$A"24B@( ~ 9B9, *$        < > ?0D¨9f?Ae ‡ .(;1.D 4H&.Ct iY% *  7à ì   úÈ  J  <    W 0%$  ""I! *  D  ,4A'¾4J" .0f6D4pÆZ{+*ŸD_wqi;ÐW1G("% %T7F}AG!1#%  JG 3 ÿ€€ '.2>Vb%&#'32&'!>?>'&' &>"6&#">&'>26 $$ *b6”~ˆ#¸ê„= þÉþ–XP2“Š{&%gx|ŠÀ .ÜÒÇW)o”üñO¹øLOƒsEzG<ä’ CK}E $MFD<5+ zÎþŸþ^þŸÎÎa¢a$ñMWŽM –“1>]|áYY›^D ÖÕ¥Aò—ï<ïæKåm‘¤ªÔE6<þ"è² @9I5*Èþ^þŸÎÎa¢aÎÎÿ€€>^4./.543232654.#"#".#"32>#"'#"$&547&54632632•':XM1h*+D($,/9p¬`D€oC&JV<’Z PA3Q1*223ô©I†oBkែhMIþû½oPែhMI½oPÙ2S6, M!"@-7Y.?oI=[<%$('3 -- <-\ƒ%FuŸáPo½IMh‚ŸáPo½þûIMhÿ€€#< "'&4762 '&#"327#1"'&'&4?6262Ëýµ4—5ýµ55K5–5 þr¼*9;)x**–%<'k5‚xý& þiy ,ü>*ýµ55K5–5K55þ÷þq¼*)y(;:*þh )k5–=x*ý& ˜*xü?ÿ€€/%4&#!"3!264&#!"3!26#!"&5463!2Àþ à þ à &ú€&&€&ÀüŽ€ý€ú€&&€&&ÿà19#"'#++"&5#"&5475##"&54763!2"&4628(3ã-÷ &ÀB. .BÀ& ÷-ã3(8Ig€gIþ`ƒºƒƒºà(8+U„þe&þð.BB.&›„þ«+8(€kkþ€`ºƒƒºƒÿà%-"&5#"&5#"&5#"&5463!2"&4628P8@B\B@B\B@8P8pP€Ppþàƒºƒƒº@þ`(88(`üp.BB.Ðþ0.BB.þ (88( Pppͺƒƒºƒÿ€€!%>&'&#"'.$ $$ ^/(V=$<;$=V).XÎþŸþ^þŸÎÎa¢aêÙJ`"(("`JŽþ^þŸÎÎa¢aÎÎ,ÿÔÿI4."2>%'%"/'&5%&'&?'&767%476762%6À[›ÕêÕ›[[›ÕêÕ›oþÜ þÜ´ ´þÜ þÜ ´´ $ $´ " ´$ $ ´´  êÕ›[[›ÕêÕ›[[›5`þÎ ^ø ø^ 2` øø `2 ^ø ø^ þÎ` øø ÿ€¾1%#"$54732$%#"$&546$763276î68¶þÊ´hÉÿf«í‚&^þ…àœþäÎzsÅ™,!V[’ú”vn)é ´6¶À¥<þ®×‚í«f{ÃËózΜ™Ì}))NÏs”ú’3(@ÿ€À€ +4&#!"3!2#!"&5463!2#!"&5463!2@&ÿ&&f&ú€&&€&@&ú&&&¦4&&4&ü@&&À&&¦ÿ&&&& ÿ `ÀBH+"/##"./#"'.?&5#"&46;'&462!76232!46 `&àCÐ6Æ@Bb0€3eI;·Ê:à&&à­&4­L­4&­àþFý€» »Z4&«wÑ4Å) €ü€'' Ï5ãr &4&&­4&­­&4­þÚ…»»ÿÿ}G†3#&/.#./.'&4?63%27>'./&'&7676>767>?>%6}­)N @2*&ÿ@P9A #sG–q] #lh<* 46+(  < 5ºR5"*>%"/ +[>hy  ÿª÷K !/Ui%6&'&676&'&6'.7>%.$76$% $.5476$6?62'.76&&'&676%.76&'..676£#"NDQt µ-âokQ//Ñjo_  þÿ’ßþÛ  ’ß%&JÁþýþæþôÕ‚‹€©YJA-‹Ö.-- 9\DtT+X?*<UW3' 26$>>¬W0 {òü"F!"E ›   ^f`$"¹_]\µ<`”Fí’`”FíŽDƒh>Cw·ls€©†J@‘ ;=?s  :i_^{8+?` ) O`ýs2R´DE58/Kÿ€r #"'>7&4$&5m«ÅÄ«ŠÃ"#Ãþ›ý̵§$5µÌý³$§"^^Wøø=þüþac×»EÖý*þè×cŸüåÖþ»ÿzk./"&4636$7.'>67.'>65.67>&/>z X^hc^O<qþŸÐ­+f$H^XbVS!rȇr?5GD_RV@-FbV=3! G84&3Im<$/6X_D'=NUTL;2KPwtޱPt=  äþù&Õ¼ ,J~S/#NL,ƒ 8JsF);??1zIEJpqDIPZXSF6[?5:NR=“ˆ;.&1ÿë +!"&=!!%!5463!2ësQ9þüýïQsÖû*Öû*Öû*sQNQsBUwþó wUBFÿÿHÿÿŒCCTwwÿ€€%1#"&=!"&=463!54632.  6 $$ € þÀ  þ   ` ?©’úþØú’’ú(úrÎþŸþ^þŸÎÎa¢aŽ þÀ  À À À þÁ«(ú’’úþØú’’_þ^þŸÎÎa¢aÎÎÿ€€%1#!#"'&47632!2.  6 $$ € þ  þÁ @  `  ’úþØú’’ú(úrÎþŸþ^þŸÎÎa¢aàÀ À ?  @  Àþÿ(ú’’úþØú’’_þ^þŸÎÎa¢aÎÎÿ€€/#"'&476324&#!"3!26#!"&5463!2&þ@À& ü@  À ©wü@w©©wÀw©Àý€& @B@ &üÆÀ  ü@ Íü@w©©wÀw©©ÿ€€"&462  >& $$ –Ô––Ô*þØú’’ú(ú’’rÎþŸþ^þŸÎÎa¢aêÔ––Ô– ’úþØú’’ú(ú½þ^þŸÎÎa¢aÎÎÿ]à6#"$54732>%#"'!"&'&7>32'!!!2ÿf:þлœþ÷›Ñªz’¹~Õu:ÿ (ïþ(%`V6B^hD%§þiÇ(ä]̳ޛ œµ*>ƒ6ß…¹þù‚Ýr€#Ý! 3?^BEaþ߀€#þ9ÿ€€;K6'&6'.'&'.'&667676#!"&5463!2æ%4‡0C>9PC/+,+  /9F6¥( C1 $$*=+T"ƒwh‰(©wü@w©©wÀw©ƒU/A*7U1.L4[N .QAg#%@) ”$)7 .’3c M ‹3&ü@w©©wÀw©©€€D+"&5#"'&=4?5#"'&=4?546;2%6%66546;2€½þ¼¿ × é× é wþwwþw¼ À¿þ¼½cB €G]B €Gúµt€y]t€yþ ¾€€#3C#!+"&5!"&=463!46;2!24&#!"3!26#!"&5463!2€þ @þ `@`€^BüÀB^^B@B^€©wüÀw©©w@w©à@þ `@`þ þ2@B^^BüÀB^^‚üÀw©©w@w©©‚^rg_<õ ÎjWÎjWÿÿÿ€þÝ€ÿÿÿÿ€Ž€pUÀÀ€À3U3€ô]€€€€€€y€n€€€€€2€€@€€€€€€ €€€€€€€€z€€€5€u@€5€5 €€€z€€€€5€5€€€€@€€€€€€€€€€,€€€€€€€€€€s€€€@€€€@€€(€€€€€€€€€€€€@€€@- €M€M€-€ €M€M€€€€€ €€€€€@@€ €-€€€€`€€b€€€€ €€€$€ €€€6€4‚8€"€"""""€€€@€€N@€€€ €,@€ €ÿÿ€€€€P’ÔBp®<$‚HÎú<¦üTÄfüT’à H ¨ þ R Ú , š D x Ê 6 \ ¤D¨L¦XŠâ*ªD¶x8”ðJ¤NÀ2f²ö$P˜Žø`Ö"Vt¤êLv¤ð$~À*‚h¼þ 6 n ¨ â!&!v!Æ!ü""p"¼#&#˜#â$8$À%%f& &¼&ü'`'Œ'¼(*(‚(¦(ì)")X)¬* *B*¦+,n,ä-z..:.’.ð/@/ˆ/æ0D0¬1~1â2l2à33R3Ì44>4¼4ö585œ66V6¬7"7²8P8à9|9Ê::b:°=¾>>l>–>à?R?Ø@l@š@ÔA²BBxBâCCDC®DZDîE–FrFÔGDG²HH®IFI¢IÀIÞIüJJLJ€JžJ¼KK\K®LJLÈM*M¾MøNhNìOFOÈPPjP¾QDQ²QîR2RjRÈS2TÌVV’VúWLWxWÄXX\X¨XôY@YjY”Y¾YèZ0Z~Z¼[[6[’[î\V\t\¸]6]x]â]â]â^P^¾__~```Þa‚aÂb*bŒbÚccXcÆd–dîe0edeÎf6fffðg@g²gêhNh¼i i:iziºiüj?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqï rstuvwxyz{|}~€‚ƒ„…†‡ˆ‰Š‹ŒŽ‘’“”•–—˜™š›œžŸ ¡¢£¤¥¦§¨©ª«¬­®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ     " !"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abÒcdefghijklmnopqrstuvwxyz{|}~€‚ƒ„…”uni00A0uni2000uni2001uni2002uni2003uni2004uni2005uni2006uni2007uni2008uni2009uni200Auni202Funi205FuniE000glassmusicsearchenvelopeheartstar star_emptyuserfilmth_largethth_listokremovezoom_inzoom_outoffsignalcogtrashhomefile_alttimeroad download_altdownloaduploadinbox play_circlerepeatrefreshlist_altlockflag headphones volume_off volume_down volume_upqrcodebarcodetagtagsbookbookmarkprintcamerafontbolditalic text_height text_width align_left align_center align_right align_justifylist indent_left indent_rightfacetime_videopicturepencil map_markeradjusttinteditsharecheckmove step_backward fast_backwardbackwardplaypausestopforward fast_forward step_forwardeject chevron_left chevron_right plus_sign minus_sign remove_signok_sign question_sign info_sign screenshot remove_circle ok_circle ban_circle arrow_left arrow_rightarrow_up arrow_down share_alt resize_full resize_smallexclamation_signgiftleaffireeye_open eye_close warning_signplanecalendarrandomcommentmagnet chevron_up chevron_downretweet shopping_cart folder_close folder_openresize_verticalresize_horizontal bar_chart twitter_sign facebook_sign camera_retrokeycogscomments thumbs_up_altthumbs_down_alt star_half heart_emptysignout linkedin_signpushpin external_linksignintrophy github_sign upload_altlemonphone check_emptybookmark_empty phone_signtwitterfacebookgithubunlock credit_cardrsshddbullhornbell certificate hand_right hand_lefthand_up hand_downcircle_arrow_leftcircle_arrow_rightcircle_arrow_upcircle_arrow_downglobewrenchtasksfilter briefcase fullscreengrouplinkcloudbeakercutcopy paper_clipsave sign_blankreorderulol strikethrough underlinetablemagictruck pinterestpinterest_signgoogle_plus_sign google_plusmoney caret_downcaret_up caret_left caret_rightcolumnssort sort_downsort_up envelope_altlinkedinundolegal dashboard comment_alt comments_altboltsitemapumbrellapaste light_bulbexchangecloud_download cloud_uploaduser_md stethoscopesuitcasebell_altcoffeefood file_text_altbuildinghospital ambulancemedkit fighter_jetbeerh_signf0fedouble_angle_leftdouble_angle_rightdouble_angle_updouble_angle_down angle_left angle_rightangle_up angle_downdesktoplaptoptablet mobile_phone circle_blank quote_left quote_rightspinnercirclereply github_altfolder_close_altfolder_open_alt expand_alt collapse_altsmilefrownmehgamepadkeyboardflag_altflag_checkeredterminalcode reply_allstar_half_emptylocation_arrowcrop code_forkunlink_279 exclamation superscript subscript_283 puzzle_piece microphonemicrophone_offshieldcalendar_emptyfire_extinguisherrocketmaxcdnchevron_sign_leftchevron_sign_rightchevron_sign_upchevron_sign_downhtml5css3anchor unlock_altbullseyeellipsis_horizontalellipsis_vertical_303 play_signticketminus_sign_alt check_minuslevel_up level_down check_sign edit_sign_312 share_signcompasscollapse collapse_top_317eurgbpusdinrjpyrubkrwbtcfile file_textsort_by_alphabet_329sort_by_attributessort_by_attributes_alt sort_by_ordersort_by_order_alt_334_335 youtube_signyoutubexing xing_sign youtube_playdropbox stackexchange instagramflickradnf171bitbucket_signtumblr tumblr_signlong_arrow_down long_arrow_uplong_arrow_leftlong_arrow_rightwindowsandroidlinuxdribbleskype foursquaretrellofemalemalegittipsun_366archivebugvkweiborenren_372stack_exchange_374arrow_circle_alt_left_376dot_circle_alt_378 vimeo_square_380 plus_square_o_382_383_384_385_386_387_388_389Rw¹×orson-charts-2.1.0/src/test/000077500000000000000000000000001417331271500157065ustar00rootroot00000000000000orson-charts-2.1.0/src/test/java/000077500000000000000000000000001417331271500166275ustar00rootroot00000000000000orson-charts-2.1.0/src/test/java/org/000077500000000000000000000000001417331271500174165ustar00rootroot00000000000000orson-charts-2.1.0/src/test/java/org/jfree/000077500000000000000000000000001417331271500205115ustar00rootroot00000000000000orson-charts-2.1.0/src/test/java/org/jfree/chart3d/000077500000000000000000000000001417331271500220415ustar00rootroot00000000000000orson-charts-2.1.0/src/test/java/org/jfree/chart3d/Chart3DTest.java000066400000000000000000000224671417331271500250070ustar00rootroot00000000000000/* =========================================================== * Orson Charts : a 3D chart library for the Java(tm) platform * =========================================================== * * (C)opyright 2013-2022, by David Gilbert. All rights reserved. * * https://github.com/jfree/orson-charts * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . * * [Oracle and Java are registered trademarks of Oracle and/or its affiliates. * Other names may be trademarks of their respective owners.] * * If you do not wish to be bound by the terms of the GPL, an alternative * commercial license can be purchased. For details, please see visit the * Orson Charts home page: * * http://www.object-refinery.com/orsoncharts/index.html * */ package org.jfree.chart3d; import static org.junit.jupiter.api.Assertions.assertTrue; import static org.junit.jupiter.api.Assertions.assertFalse; import static org.junit.jupiter.api.Assertions.assertEquals; import org.junit.jupiter.api.Test; import java.awt.Color; import java.awt.GradientPaint; import org.jfree.chart3d.data.DefaultKeyedValues; import org.jfree.chart3d.data.PieDataset3D; import org.jfree.chart3d.data.StandardPieDataset3D; import org.jfree.chart3d.data.category.CategoryDataset3D; import org.jfree.chart3d.data.category.StandardCategoryDataset3D; import org.jfree.chart3d.data.xyz.XYZDataset; import org.jfree.chart3d.data.xyz.XYZSeries; import org.jfree.chart3d.data.xyz.XYZSeriesCollection; import org.jfree.chart3d.legend.LegendAnchor; import org.jfree.chart3d.legend.StandardLegendBuilder; import org.jfree.chart3d.style.ChartStyles; import org.jfree.chart3d.table.StandardRectanglePainter; /** * Tests for the {@link Chart3D} class. */ public class Chart3DTest { /** * Checks for the equals() method. */ @Test public void checkEquals() { Chart3D c1 = Chart3DFactory.createPieChart("title", "subtitle", createPieDataset()); Chart3D c2 = Chart3DFactory.createPieChart("title", "subtitle", createPieDataset()); assertTrue(c1.equals(c2)); assertFalse(c1.equals(null)); // background painter c1.setBackground(new StandardRectanglePainter(Color.RED)); assertFalse(c1.equals(c2)); c2.setBackground(new StandardRectanglePainter(Color.RED)); assertTrue(c1.equals(c2)); // title c1.setTitle("ABC"); assertFalse(c1.equals(c2)); c2.setTitle("ABC"); assertTrue(c1.equals(c2)); c1.setTitle((String) null); assertFalse(c1.equals(c2)); c2.setTitle((String) null); assertTrue(c1.equals(c2)); // title anchor c1.setTitleAnchor(TitleAnchor.BOTTOM_LEFT); assertFalse(c1.equals(c2)); c2.setTitleAnchor(TitleAnchor.BOTTOM_LEFT); assertTrue(c1.equals(c2)); // legend builder c1.setLegendBuilder(null); assertFalse(c1.equals(c2)); c2.setLegendBuilder(null); assertTrue(c1.equals(c2)); // legend anchor c1.setLegendAnchor(LegendAnchor.CENTER_LEFT); assertFalse(c1.equals(c2)); c2.setLegendAnchor(LegendAnchor.CENTER_LEFT); assertTrue(c1.equals(c2)); // legend orientation c1.setLegendOrientation(Orientation.VERTICAL); assertFalse(c1.equals(c2)); c2.setLegendOrientation(Orientation.VERTICAL); assertTrue(c1.equals(c2)); StandardLegendBuilder slb1 = new StandardLegendBuilder(); slb1.setHeader("ABC"); c1.setLegendBuilder(slb1); assertFalse(c1.equals(c2)); StandardLegendBuilder slb2 = new StandardLegendBuilder(); slb2.setHeader("ABC"); c2.setLegendBuilder(slb2); assertTrue(c1.equals(c2)); // chart box color c1.setChartBoxColor(Color.CYAN); assertFalse(c1.equals(c2)); c2.setChartBoxColor(Color.CYAN); assertTrue(c1.equals(c2)); // projDist c1.setProjDistance(123); assertFalse(c1.equals(c2)); c2.setProjDistance(123); assertTrue(c1.equals(c2)); // style c1.setStyle(ChartStyles.createIceCubeStyle()); assertFalse(c1.equals(c2)); c2.setStyle(ChartStyles.createIceCubeStyle()); assertTrue(c1.equals(c2)); } /** * A check for serialization. */ @Test public void testSerializationPieChart() { Chart3D c1 = Chart3DFactory.createPieChart("title", "subtitle", createPieDataset()); Chart3D c2 = (Chart3D) TestUtils.serialized(c1); assertEquals(c1, c2); // check that gradient paint is correctly serialized c1.setBackground(new StandardRectanglePainter(new GradientPaint(1f, 2f, Color.RED, 3f, 4f, Color.BLUE))); c2 = (Chart3D) TestUtils.serialized(c1); assertEquals(c1, c2); } /** * A check for serialization of area charts. */ @Test public void testSerializationAreaChart() { Chart3D c1 = Chart3DFactory.createAreaChart("title", "subtitle", createCategoryDataset(), "rowAxis", "columnAxis", "valueAxis"); Chart3D c2 = (Chart3D) TestUtils.serialized(c1); assertEquals(c1, c2); } /** * A check for serialization of bar charts. */ @Test public void testSerializationBarChart() { Chart3D c1 = Chart3DFactory.createBarChart("title", "subtitle", createCategoryDataset(), "rowAxis", "columnAxis", "valueAxis"); Chart3D c2 = (Chart3D) TestUtils.serialized(c1); assertEquals(c1, c2); } /** * A check for serialization of line charts. */ @Test public void testSerializationLineChart() { Chart3D c1 = Chart3DFactory.createLineChart("title", "subtitle", createCategoryDataset(), "rowAxis", "columnAxis", "valueAxis"); Chart3D c2 = (Chart3D) TestUtils.serialized(c1); assertEquals(c1, c2); } /** * A check for serialization of stacked bar charts. */ @Test public void testSerializationStackedBarChart() { Chart3D c1 = Chart3DFactory.createStackedBarChart("title", "subtitle", createCategoryDataset(), "rowAxis", "columnAxis", "valueAxis"); Chart3D c2 = (Chart3D) TestUtils.serialized(c1); assertEquals(c1, c2); } /** * A check for serialization of scatter charts. */ @Test public void testSerializationScatterChart() { Chart3D c1 = Chart3DFactory.createScatterChart("title", "subtitle", createXYZDataset(), "rowAxis", "columnAxis", "valueAxis"); Chart3D c2 = (Chart3D) TestUtils.serialized(c1); assertEquals(c1, c2); } /** * A check for serialization of scatter charts. */ @Test public void testSerializationXYZBarChart() { Chart3D c1 = Chart3DFactory.createXYZBarChart("title", "subtitle", createXYZDataset(), "rowAxis", "columnAxis", "valueAxis"); Chart3D c2 = (Chart3D) TestUtils.serialized(c1); assertEquals(c1, c2); } /** * After deserializing, check that we can still register listeners. */ @Test public void testListenerStorageAfterDeserialization() { Chart3D c1 = Chart3DFactory.createPieChart("title", "subtitle", createPieDataset()); Chart3D c2 = (Chart3D) TestUtils.serialized(c1); assertEquals(c1, c2); c2.addChangeListener(new Chart3DChangeListener() { @Override public void chartChanged(Chart3DChangeEvent event) { throw new UnsupportedOperationException("Not supported yet."); //To change body of generated methods, choose Tools | Templates. } }); } private PieDataset3D createPieDataset() { StandardPieDataset3D dataset = new StandardPieDataset3D<>(); dataset.add("United States", 30.0); dataset.add("France", 20.0); return dataset; } private CategoryDataset3D createCategoryDataset() { StandardCategoryDataset3D dataset = new StandardCategoryDataset3D<>(); DefaultKeyedValues s1 = new DefaultKeyedValues<>(); s1.put("Q1", 1.0); s1.put("Q2", 7.0); s1.put("Q3", 3.0); s1.put("Q4", 4.0); dataset.addSeriesAsRow("Acme Widgets Ltd", s1); return dataset; } private XYZDataset createXYZDataset() { XYZSeries s1 = new XYZSeries<>("S1"); s1.add(1, 2, 3); XYZSeriesCollection dataset = new XYZSeriesCollection<>(); dataset.add(s1); return dataset; } } orson-charts-2.1.0/src/test/java/org/jfree/chart3d/TestUtils.java000066400000000000000000000052651417331271500246540ustar00rootroot00000000000000/* =========================================================== * Orson Charts : a 3D chart library for the Java(tm) platform * =========================================================== * * (C)opyright 2013-2022, by David Gilbert. All rights reserved. * * https://github.com/jfree/orson-charts * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . * * [Oracle and Java are registered trademarks of Oracle and/or its affiliates. * Other names may be trademarks of their respective owners.] * * If you do not wish to be bound by the terms of the GPL, an alternative * commercial license can be purchased. For details, please see visit the * Orson Charts home page: * * http://www.object-refinery.com/orsoncharts/index.html * */ package org.jfree.chart3d; import java.io.ByteArrayInputStream; import java.io.ByteArrayOutputStream; import java.io.IOException; import java.io.ObjectInput; import java.io.ObjectInputStream; import java.io.ObjectOutput; import java.io.ObjectOutputStream; import java.io.Serializable; /** * Some utility methods for serialization. */ public class TestUtils { /** * Returns a copy of an object that is obtained by serializing the original * object to a byte array then deserializing the bytes from the byte * array. * * @param original the original object ({@code null} not permitted). * * @return A copy of the original object. */ public static Object serialized(Serializable original) { Object result = null; ByteArrayOutputStream buffer = new ByteArrayOutputStream(); ObjectOutput out; try { out = new ObjectOutputStream(buffer); out.writeObject(original); out.close(); ObjectInput in = new ObjectInputStream( new ByteArrayInputStream(buffer.toByteArray())); result = in.readObject(); in.close(); } catch (IOException e) { throw new RuntimeException(e); } catch (ClassNotFoundException e) { throw new RuntimeException(e); } return result; } } orson-charts-2.1.0/src/test/java/org/jfree/chart3d/axis/000077500000000000000000000000001417331271500230055ustar00rootroot00000000000000orson-charts-2.1.0/src/test/java/org/jfree/chart3d/axis/LogAxis3DTest.java000066400000000000000000000151021417331271500262440ustar00rootroot00000000000000/* =========================================================== * Orson Charts : a 3D chart library for the Java(tm) platform * =========================================================== * * Copyright 2013-2022, by David Gilbert. All rights reserved. * * https://github.com/jfree/orson-charts * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . * * [Oracle and Java are registered trademarks of Oracle and/or its affiliates. * Other names may be trademarks of their respective owners.] * * If you do not wish to be bound by the terms of the GPL, an alternative * commercial license can be purchased. For details, please see visit the * Orson Charts home page: * * http://www.object-refinery.com/orsoncharts/index.html * */ package org.jfree.chart3d.axis; import java.awt.BasicStroke; import java.awt.Color; import java.awt.Font; import java.awt.GradientPaint; import java.text.DecimalFormat; import org.junit.jupiter.api.Test; import org.jfree.chart3d.TestUtils; import static org.junit.jupiter.api.Assertions.*; /** * Tests for the {@link LogAxis3D} class. */ public class LogAxis3DTest { @Test public void testEquals() { LogAxis3D axis1 = new LogAxis3D("Label"); LogAxis3D axis2 = new LogAxis3D("Label"); assertEquals(axis1, axis2); assertNotEquals(null, axis1); // axis label axis1.setLabel("Label2"); assertNotEquals(axis1, axis2); axis2.setLabel("Label2"); assertEquals(axis1, axis2); // axis label can be null also axis1.setLabel(null); assertNotEquals(axis1, axis2); axis2.setLabel(null); assertEquals(axis1, axis2); // label font axis1.setLabelFont(new Font("Dialog", Font.PLAIN, 2)); assertNotEquals(axis1, axis2); axis2.setLabelFont(new Font("Dialog", Font.PLAIN, 2)); assertEquals(axis1, axis2); // label color axis1.setLabelColor(Color.RED); assertNotEquals(axis1, axis2); axis2.setLabelColor(Color.RED); assertEquals(axis1, axis2); // line stroke axis1.setLineStroke(new BasicStroke(0.5f)); assertNotEquals(axis1, axis2); axis2.setLineStroke(new BasicStroke(0.5f)); assertEquals(axis1, axis2); // line color axis1.setLineColor(Color.BLUE); assertNotEquals(axis1, axis2); axis2.setLineColor(Color.BLUE); assertEquals(axis1, axis2); // tickLabelsVisible axis1.setTickLabelsVisible(false); assertNotEquals(axis1, axis2); axis2.setTickLabelsVisible(false); assertEquals(axis1, axis2); // tick label font axis1.setTickLabelFont(new Font("Dialog", Font.PLAIN, 5)); assertNotEquals(axis1, axis2); axis2.setTickLabelFont(new Font("Dialog", Font.PLAIN, 5)); assertEquals(axis1, axis2); // tick label color axis1.setTickLabelColor(Color.GREEN); assertNotEquals(axis1, axis2); axis2.setTickLabelColor(Color.GREEN); assertEquals(axis1, axis2); // axis visible axis1.setVisible(false); assertNotEquals(axis1, axis2); axis2.setVisible(false); assertEquals(axis1, axis2); axis1.setLowerMargin(0.123); assertNotEquals(axis1, axis2); axis2.setLowerMargin(0.123); assertEquals(axis1, axis2); axis1.setUpperMargin(0.321); assertNotEquals(axis1, axis2); axis2.setUpperMargin(0.321); assertEquals(axis1, axis2); axis1.setTickMarkLength(123); assertNotEquals(axis1, axis2); axis2.setTickMarkLength(123); assertEquals(axis1, axis2); axis1.setTickMarkPaint(new GradientPaint(1f, 2f, Color.BLUE, 3f, 4f, Color.GREEN)); assertNotEquals(axis1, axis2); axis2.setTickMarkPaint(new GradientPaint(1f, 2f, Color.BLUE, 3f, 4f, Color.GREEN)); assertEquals(axis1, axis2); axis1.setTickMarkStroke(new BasicStroke(1.23f)); assertNotEquals(axis1, axis2); axis2.setTickMarkStroke(new BasicStroke(1.23f)); assertEquals(axis1, axis2); axis1.setBase(5.0); assertNotEquals(axis1, axis2); axis2.setBase(5.0); assertEquals(axis1, axis2); axis1.setSmallestValue(10.0); assertNotEquals(axis1, axis2); axis2.setSmallestValue(10.0); assertEquals(axis1, axis2); axis1.setBaseSymbol("x"); assertNotEquals(axis1, axis2); axis2.setBaseSymbol("x"); assertEquals(axis1, axis2); axis1.setBaseFormatter(new DecimalFormat("0.00")); assertNotEquals(axis1, axis2); axis2.setBaseFormatter(new DecimalFormat("0.00")); assertEquals(axis1, axis2); axis1.setTickSelector(null); assertNotEquals(axis1, axis2); axis2.setTickSelector(null); assertEquals(axis1, axis2); axis1.setTickSize(12.3); assertNotEquals(axis1, axis2); axis2.setTickSize(12.3); assertEquals(axis1, axis2); axis1.setTickLabelFormatter(new DecimalFormat("0.000")); assertNotEquals(axis1, axis2); axis2.setTickLabelFormatter(new DecimalFormat("0.000")); assertEquals(axis1, axis2); axis1.setTickLabelFactor(1.2); assertNotEquals(axis1, axis2); axis2.setTickLabelFactor(1.2); assertEquals(axis1, axis2); } /** * Checks for serialization support. */ @Test public void testSerialization() { LogAxis3D axis1 = new LogAxis3D("T"); LogAxis3D axis2 = (LogAxis3D) TestUtils.serialized(axis1); assertEquals(axis1, axis2); axis1.setTickMarkPaint(new GradientPaint(9f, 10f, Color.PINK, 11f, 12f, Color.BLACK)); axis2 = (LogAxis3D) TestUtils.serialized(axis1); assertEquals(axis1, axis2); } } orson-charts-2.1.0/src/test/java/org/jfree/chart3d/axis/NumberAxis3DTest.java000066400000000000000000000234441417331271500267630ustar00rootroot00000000000000/* =========================================================== * Orson Charts : a 3D chart library for the Java(tm) platform * =========================================================== * * (C)opyright 2013-2022, by David Gilbert. All rights reserved. * * https://github.com/jfree/orson-charts * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . * * [Oracle and Java are registered trademarks of Oracle and/or its affiliates. * Other names may be trademarks of their respective owners.] * * If you do not wish to be bound by the terms of the GPL, an alternative * commercial license can be purchased. For details, please see visit the * Orson Charts home page: * * http://www.object-refinery.com/orsoncharts/index.html * */ package org.jfree.chart3d.axis; import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertNotEquals; import static org.junit.jupiter.api.Assertions.assertNull; import static org.junit.jupiter.api.Assertions.assertNotNull; import static org.junit.jupiter.api.Assertions.assertTrue; import static org.junit.jupiter.api.Assertions.assertFalse; import org.junit.jupiter.api.Test; import java.awt.BasicStroke; import java.awt.Color; import java.awt.Font; import java.awt.GradientPaint; import java.text.DecimalFormat; import org.jfree.chart3d.TestUtils; import org.jfree.chart3d.data.Range; /** * Checks for the {@link NumberAxis3D} class. */ public class NumberAxis3DTest implements Axis3DChangeListener { @Test public void checkSetVisibleFiresChangeEvent() { NumberAxis3D axis1 = new NumberAxis3D("X"); axis1.addChangeListener(this); assertNull(this.lastEvent); axis1.setVisible(false); assertNotNull(this.lastEvent); this.lastEvent = null; } @Test public void checkSetLabelFiresChangeEvent() { NumberAxis3D axis1 = new NumberAxis3D("X"); axis1.addChangeListener(this); assertNull(this.lastEvent); axis1.setLabel("XXX"); assertNotNull(this.lastEvent); this.lastEvent = null; } @Test public void checkSetLabelFontFiresChangeEvent() { NumberAxis3D axis1 = new NumberAxis3D("X"); axis1.addChangeListener(this); assertNull(this.lastEvent); axis1.setLabelFont(new Font("Dialog", Font.BOLD, 7)); assertNotNull(this.lastEvent); this.lastEvent = null; } @Test public void checkSetLineStrokeFiresChangeEvent() { NumberAxis3D axis1 = new NumberAxis3D("X"); axis1.addChangeListener(this); assertNull(this.lastEvent); axis1.setLineStroke(new BasicStroke(1.0f)); assertNotNull(this.lastEvent); this.lastEvent = null; } @Test public void checkSetLineColorFiresChangeEvent() { NumberAxis3D axis1 = new NumberAxis3D("X"); axis1.addChangeListener(this); assertNull(this.lastEvent); axis1.setLineColor(Color.RED); assertNotNull(this.lastEvent); this.lastEvent = null; } @Test public void checkSetRangeFiresChangeEvent() { NumberAxis3D axis1 = new NumberAxis3D("X"); axis1.addChangeListener(this); assertNull(this.lastEvent); axis1.setRange(new Range(1, 2)); assertNotNull(this.lastEvent); this.lastEvent = null; } @Test public void checkSetTickSizeFiresChangeEvent() { NumberAxis3D axis1 = new NumberAxis3D("X"); axis1.addChangeListener(this); assertNull(this.lastEvent); axis1.setTickSize(5.0); assertNotNull(this.lastEvent); this.lastEvent = null; } @Test public void checkSetTickLabelFontFiresChangeEvent() { NumberAxis3D axis1 = new NumberAxis3D("X"); axis1.addChangeListener(this); assertNull(this.lastEvent); axis1.setTickLabelFont(new Font("Dialog", Font.PLAIN, 11)); assertNotNull(this.lastEvent); this.lastEvent = null; } @Test public void checkEquals() { NumberAxis3D axis1 = new NumberAxis3D("X"); NumberAxis3D axis2 = new NumberAxis3D("X"); assertTrue(axis1.equals(axis2)); axis1.setLabel("ZZZ"); assertNotEquals(axis1, axis2); axis2.setLabel("ZZZ"); assertEquals(axis1, axis2); axis1.setLabelFont(new Font("Dialog", Font.PLAIN, 8)); assertNotEquals(axis1, axis2); axis2.setLabelFont(new Font("Dialog", Font.PLAIN, 8)); assertEquals(axis1, axis2); axis1.setLineStroke(new BasicStroke(2.0f)); assertNotEquals(axis1, axis2); axis2.setLineStroke(new BasicStroke(2.0f)); assertEquals(axis1, axis2); axis1.setLineColor(Color.RED); assertNotEquals(axis1, axis2); axis2.setLineColor(Color.RED); assertEquals(axis1, axis2); axis1.setRange(new Range(1, 2)); assertNotEquals(axis1, axis2); axis2.setRange(new Range(1, 2)); assertEquals(axis1, axis2); axis1.setAutoAdjustRange(true); assertFalse(axis1.equals(axis2)); axis2.setAutoAdjustRange(true); assertTrue(axis1.equals(axis2)); axis1.setLowerMargin(0.123); assertFalse(axis1.equals(axis2)); axis2.setLowerMargin(0.123); assertTrue(axis1.equals(axis2)); axis1.setUpperMargin(0.123); assertFalse(axis1.equals(axis2)); axis2.setUpperMargin(0.123); assertTrue(axis1.equals(axis2)); axis1.setAutoRangeIncludeZero(true); assertFalse(axis1.equals(axis2)); axis2.setAutoRangeIncludeZero(true); assertTrue(axis1.equals(axis2)); axis1.setAutoRangeStickyZero(false); assertFalse(axis1.equals(axis2)); axis2.setAutoRangeStickyZero(false); assertTrue(axis1.equals(axis2)); axis1.setDefaultAutoRange(new Range(5, 10)); assertFalse(axis1.equals(axis2)); axis2.setDefaultAutoRange(new Range(5, 10)); assertTrue(axis1.equals(axis2)); axis1.setTickSelector(new NumberTickSelector(true)); assertFalse(axis1.equals(axis2)); axis2.setTickSelector(new NumberTickSelector(true)); assertTrue(axis1.equals(axis2)); axis1.setTickSelector(null); assertFalse(axis1.equals(axis2)); axis2.setTickSelector(null); assertTrue(axis1.equals(axis2)); axis1.setTickSize(1.23); assertNotEquals(axis1, axis2); axis2.setTickSize(1.23); assertEquals(axis1, axis2); axis1.setTickLabelFormatter(new DecimalFormat("0.0000")); assertFalse(axis1.equals(axis2)); axis2.setTickLabelFormatter(new DecimalFormat("0.0000")); assertTrue(axis1.equals(axis2)); axis1.setTickLabelOrientation(LabelOrientation.PERPENDICULAR); assertFalse(axis1.equals(axis2)); axis2.setTickLabelOrientation(LabelOrientation.PERPENDICULAR); assertTrue(axis1.equals(axis2)); axis1.setTickLabelFactor(1.23); assertFalse(axis1.equals(axis2)); axis2.setTickLabelFactor(1.23); assertTrue(axis1.equals(axis2)); axis1.setTickLabelFont(new Font("Dialog", Font.BOLD, 20)); assertNotEquals(axis1, axis2); axis2.setTickLabelFont(new Font("Dialog", Font.BOLD, 20)); assertEquals(axis1, axis2); axis1.setTickLabelOffset(2.2); assertFalse(axis1.equals(axis2)); axis2.setTickLabelOffset(2.2); assertTrue(axis1.equals(axis2)); axis1.setTickMarkLength(1.21); assertFalse(axis1.equals(axis2)); axis2.setTickMarkLength(1.21); assertTrue(axis1.equals(axis2)); axis1.setTickMarkPaint(Color.RED); assertFalse(axis1.equals(axis2)); axis2.setTickMarkPaint(Color.RED); assertTrue(axis1.equals(axis2)); axis1.setTickMarkStroke(new BasicStroke(2f)); assertFalse(axis1.equals(axis2)); axis2.setTickMarkStroke(new BasicStroke(2f)); assertTrue(axis1.equals(axis2)); axis1.setVisible(false); assertNotEquals(axis1, axis2); axis2.setVisible(false); assertEquals(axis1, axis2); } /** * Checks for serialization support. */ @Test public void testSerialization() { NumberAxis3D axis1 = new NumberAxis3D("T"); NumberAxis3D axis2 = (NumberAxis3D) TestUtils.serialized(axis1); assertTrue(axis1.equals(axis2)); axis1.setLabelColor(Color.CYAN); axis2 = (NumberAxis3D) TestUtils.serialized(axis1); assertTrue(axis1.equals(axis2)); axis1.setTickMarkPaint(new GradientPaint(5f, 6f, Color.GREEN, 7f, 8f, Color.YELLOW)); axis2 = (NumberAxis3D) TestUtils.serialized(axis1); assertTrue(axis1.equals(axis2)); axis1.setTickMarkPaint(new GradientPaint(9f, 10f, Color.PINK, 11f, 12f, Color.BLACK)); axis2 = (NumberAxis3D) TestUtils.serialized(axis1); assertTrue(axis1.equals(axis2)); } private Axis3DChangeEvent lastEvent; @Override public void axisChanged(Axis3DChangeEvent event) { this.lastEvent = event; } } orson-charts-2.1.0/src/test/java/org/jfree/chart3d/axis/NumberTickSelectorTest.java000066400000000000000000000070731417331271500302630ustar00rootroot00000000000000/* =========================================================== * Orson Charts : a 3D chart library for the Java(tm) platform * =========================================================== * * (C)opyright 2013-2022, by David Gilbert. All rights reserved. * * https://github.com/jfree/orson-charts * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . * * [Oracle and Java are registered trademarks of Oracle and/or its affiliates. * Other names may be trademarks of their respective owners.] * * If you do not wish to be bound by the terms of the GPL, an alternative * commercial license can be purchased. For details, please see visit the * Orson Charts home page: * * http://www.object-refinery.com/orsoncharts/index.html * */ package org.jfree.chart3d.axis; import static org.junit.jupiter.api.Assertions.assertFalse; import static org.junit.jupiter.api.Assertions.assertTrue; import static org.junit.jupiter.api.Assertions.assertEquals; import org.junit.jupiter.api.Test; import org.jfree.chart3d.TestUtils; import static org.junit.jupiter.api.Assertions.fail; /** * Tests for the {@link NumberTickSelector} class. */ public class NumberTickSelectorTest { @Test public void testEquals() { NumberTickSelector s1 = new NumberTickSelector(); NumberTickSelector s2 = new NumberTickSelector(); assertTrue(s1.equals(s2)); s1 = new NumberTickSelector(true); assertFalse(s1.equals(s2)); s2 = new NumberTickSelector(true); assertTrue(s1.equals(s2)); } /** * Checks for serialization support. */ @Test public void testSerialization() { NumberTickSelector s1 = new NumberTickSelector(); NumberTickSelector s2 = (NumberTickSelector) TestUtils.serialized(s1); assertTrue(s1.equals(s2)); } public static final double EPSILON = 0.0000001; @Test public void testSelect() { NumberTickSelector s = new NumberTickSelector(); assertEquals(1.0, s.getCurrentTickSize(), EPSILON); double d = s.getCurrentTickSize(); s.select(10); assertEquals(s.getCurrentTickSize(), 10.0, EPSILON); s.select(14); assertEquals(s.getCurrentTickSize(), 100.0, EPSILON); s.select(1000000000000000000.0); assertEquals(s.getCurrentTickSize(), 1000000000000000000.0, EPSILON); try { s.select(0); fail("Expected an IllegalArgumentException for this case."); } catch (IllegalArgumentException e) { // expected } try { s.select(Double.POSITIVE_INFINITY); fail("Expected an IllegalArgumentException for this case."); } catch (IllegalArgumentException e) { // expected } try { s.select(Double.NEGATIVE_INFINITY); fail("Expected an IllegalArgumentException for this case."); } catch (IllegalArgumentException e) { // expected } } } orson-charts-2.1.0/src/test/java/org/jfree/chart3d/axis/StandardCategoryAxis3DTest.java000066400000000000000000000167051417331271500307730ustar00rootroot00000000000000/* =========================================================== * Orson Charts : a 3D chart library for the Java(tm) platform * =========================================================== * * (C)opyright 2013-2022, by David Gilbert. All rights reserved. * * https://github.com/jfree/orson-charts * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . * * [Oracle and Java are registered trademarks of Oracle and/or its affiliates. * Other names may be trademarks of their respective owners.] * * If you do not wish to be bound by the terms of the GPL, an alternative * commercial license can be purchased. For details, please see visit the * Orson Charts home page: * * http://www.object-refinery.com/orsoncharts/index.html * */ package org.jfree.chart3d.axis; import static org.junit.jupiter.api.Assertions.assertTrue; import static org.junit.jupiter.api.Assertions.assertFalse; import java.awt.BasicStroke; import java.awt.Color; import java.awt.Font; import java.awt.GradientPaint; import org.jfree.chart3d.TestUtils; import org.junit.jupiter.api.Test; import org.jfree.chart3d.label.StandardCategoryLabelGenerator; import org.jfree.chart3d.marker.CategoryMarker; /** * Tests for the {@link StandardCategoryAxis3D} class. */ public class StandardCategoryAxis3DTest { @Test public void testEquals() { StandardCategoryAxis3D axis1 = new StandardCategoryAxis3D("Label"); StandardCategoryAxis3D axis2 = new StandardCategoryAxis3D("Label"); assertTrue(axis1.equals(axis2)); assertFalse(axis1.equals(null)); // axis label axis1.setLabel("Label2"); assertFalse(axis1.equals(axis2)); axis2.setLabel("Label2"); assertTrue(axis1.equals(axis2)); // axis label can be null also axis1.setLabel(null); assertFalse(axis1.equals(axis2)); axis2.setLabel(null); assertTrue(axis1.equals(axis2)); // label font axis1.setLabelFont(new Font("Dialog", Font.PLAIN, 2)); assertFalse(axis1.equals(axis2)); axis2.setLabelFont(new Font("Dialog", Font.PLAIN, 2)); assertTrue(axis1.equals(axis2)); // label color axis1.setLabelColor(Color.RED); assertFalse(axis1.equals(axis2)); axis2.setLabelColor(Color.RED); assertTrue(axis1.equals(axis2)); // line stroke axis1.setLineStroke(new BasicStroke(0.5f)); assertFalse(axis1.equals(axis2)); axis2.setLineStroke(new BasicStroke(0.5f)); assertTrue(axis1.equals(axis2)); // line color axis1.setLineColor(Color.BLUE); assertFalse(axis1.equals(axis2)); axis2.setLineColor(Color.BLUE); assertTrue(axis1.equals(axis2)); // tickLabelsVisible axis1.setTickLabelsVisible(false); assertFalse(axis1.equals(axis2)); axis2.setTickLabelsVisible(false); assertTrue(axis1.equals(axis2)); // tick label font axis1.setTickLabelFont(new Font("Dialog", Font.PLAIN, 5)); assertFalse(axis1.equals(axis2)); axis2.setTickLabelFont(new Font("Dialog", Font.PLAIN, 5)); assertTrue(axis1.equals(axis2)); // tick label color axis1.setTickLabelColor(Color.GREEN); assertFalse(axis1.equals(axis2)); axis2.setTickLabelColor(Color.GREEN); assertTrue(axis1.equals(axis2)); // axis visible axis1.setVisible(false); assertFalse(axis1.equals(axis2)); axis2.setVisible(false); assertTrue(axis1.equals(axis2)); axis1.setLowerMargin(0.123); assertFalse(axis1.equals(axis2)); axis2.setLowerMargin(0.123); assertTrue(axis1.equals(axis2)); axis1.setUpperMargin(0.321); assertFalse(axis1.equals(axis2)); axis2.setUpperMargin(0.321); assertTrue(axis1.equals(axis2)); axis1.setFirstCategoryHalfWidth(true); assertFalse(axis1.equals(axis2)); axis2.setFirstCategoryHalfWidth(true); assertTrue(axis1.equals(axis2)); axis1.setLastCategoryHalfWidth(true); assertFalse(axis1.equals(axis2)); axis2.setLastCategoryHalfWidth(true); assertTrue(axis1.equals(axis2)); axis1.setTickMarkLength(123); assertFalse(axis1.equals(axis2)); axis2.setTickMarkLength(123); assertTrue(axis1.equals(axis2)); axis1.setTickMarkPaint(new GradientPaint(1f, 2f, Color.BLUE, 3f, 4f, Color.GREEN)); assertFalse(axis1.equals(axis2)); axis2.setTickMarkPaint(new GradientPaint(1f, 2f, Color.BLUE, 3f, 4f, Color.GREEN)); assertTrue(axis1.equals(axis2)); axis1.setTickMarkStroke(new BasicStroke(1.23f)); assertFalse(axis1.equals(axis2)); axis2.setTickMarkStroke(new BasicStroke(1.23f)); assertTrue(axis1.equals(axis2)); axis1.setTickLabelGenerator( new StandardCategoryLabelGenerator("{0} {1}")); assertFalse(axis1.equals(axis2)); axis2.setTickLabelGenerator( new StandardCategoryLabelGenerator("{0} {1}")); assertTrue(axis1.equals(axis2)); axis1.setTickLabelOffset(1.23); assertFalse(axis1.equals(axis2)); axis2.setTickLabelOffset(1.23); assertTrue(axis1.equals(axis2)); axis1.setTickLabelOrientation(LabelOrientation.PERPENDICULAR); assertFalse(axis1.equals(axis2)); axis2.setTickLabelOrientation(LabelOrientation.PERPENDICULAR); assertTrue(axis1.equals(axis2)); axis1.setTickLabelFactor(1.23); assertFalse(axis1.equals(axis2)); axis2.setTickLabelFactor(1.23); assertTrue(axis1.equals(axis2)); axis1.setMaxTickLabelLevels(5); assertFalse(axis1.equals(axis2)); axis2.setMaxTickLabelLevels(5); assertTrue(axis1.equals(axis2)); axis1.setMarker("M1", new CategoryMarker("A")); assertFalse(axis1.equals(axis2)); axis2.setMarker("M1", new CategoryMarker("A")); assertTrue(axis1.equals(axis2)); } /** * Checks for serialization support. */ @Test public void testSerialization() { StandardCategoryAxis3D axis1 = new StandardCategoryAxis3D("T"); StandardCategoryAxis3D axis2 = (StandardCategoryAxis3D) TestUtils.serialized(axis1); assertTrue(axis1.equals(axis2)); axis1.setTickMarkPaint(new GradientPaint(9f, 10f, Color.PINK, 11f, 12f, Color.BLACK)); axis2 = (StandardCategoryAxis3D) TestUtils.serialized(axis1); assertTrue(axis1.equals(axis2)); axis1.setMarker("M1", new CategoryMarker("C1")); axis2 = (StandardCategoryAxis3D) TestUtils.serialized(axis1); assertTrue(axis1.equals(axis2)); } } orson-charts-2.1.0/src/test/java/org/jfree/chart3d/data/000077500000000000000000000000001417331271500227525ustar00rootroot00000000000000orson-charts-2.1.0/src/test/java/org/jfree/chart3d/data/DataUtilsTest.java000066400000000000000000000346241417331271500263600ustar00rootroot00000000000000/* =========================================================== * Orson Charts : a 3D chart library for the Java(tm) platform * =========================================================== * * (C)opyright 2013-2022, by David Gilbert. All rights reserved. * * https://github.com/jfree/orson-charts * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . * * [Oracle and Java are registered trademarks of Oracle and/or its affiliates. * Other names may be trademarks of their respective owners.] * * If you do not wish to be bound by the terms of the GPL, an alternative * commercial license can be purchased. For details, please see visit the * Orson Charts home page: * * http://www.object-refinery.com/orsoncharts/index.html * */ package org.jfree.chart3d.data; import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertArrayEquals; import static org.junit.jupiter.api.Assertions.assertNull; import org.junit.jupiter.api.Test; import org.jfree.chart3d.data.category.StandardCategoryDataset3D; import org.jfree.chart3d.data.xyz.XYZDataset; import org.jfree.chart3d.data.xyz.XYZSeries; import org.jfree.chart3d.data.xyz.XYZSeriesCollection; /** * Tests for the {@link DataUtils} class. */ public class DataUtilsTest { private static final double EPSILON = 0.0000001; @Test public void testCount() { DefaultKeyedValues3D dataset = new DefaultKeyedValues3D<>(); dataset.setValue(1.0, "S1", "R1", "C1"); assertEquals(1, DataUtils.count(dataset, "S1")); dataset.setValue(2.0, "S1", "R2", "C1"); assertEquals(2, DataUtils.count(dataset, "S1")); dataset.setValue(null, "S1", "R2", "C1"); assertEquals(1, DataUtils.count(dataset, "S1")); dataset.setValue(null, "S1", "R1", "C1"); assertEquals(0, DataUtils.count(dataset, "S1")); } @Test public void testCountForRow() { DefaultKeyedValues3D dataset = new DefaultKeyedValues3D<>(); dataset.setValue(1.0, "S1", "R1", "C1"); assertEquals(1, DataUtils.countForRow(dataset, "R1")); dataset.setValue(2.0, "S2", "R1", "C1"); assertEquals(2, DataUtils.countForRow(dataset, "R1")); dataset.setValue(null, "S2", "R1", "C1"); assertEquals(1, DataUtils.countForRow(dataset, "R1")); dataset.setValue(null, "S1", "R1", "C1"); assertEquals(0, DataUtils.countForRow(dataset, "R1")); } @Test public void testCountForColumn() { DefaultKeyedValues3D dataset = new DefaultKeyedValues3D<>(); dataset.setValue(1.0, "S1", "R1", "C1"); assertEquals(1, DataUtils.countForColumn(dataset, "C1")); dataset.setValue(2.0, "S1", "R2", "C1"); assertEquals(2, DataUtils.countForColumn(dataset, "C1")); dataset.setValue(null, "S1", "R2", "C1"); assertEquals(1, DataUtils.countForColumn(dataset, "C1")); dataset.setValue(null, "S1", "R1", "C1"); assertEquals(0, DataUtils.countForColumn(dataset, "C1")); } @Test public void testTotal() { DefaultKeyedValues values = new DefaultKeyedValues<>(); assertEquals(0.0, DataUtils.total(values), EPSILON); values.put("K1", 1.0); assertEquals(1.0, DataUtils.total(values), EPSILON); values.put("K2", 2.0); assertEquals(3.0, DataUtils.total(values), EPSILON); values.put("K3", 3.0); assertEquals(6.0, DataUtils.total(values), EPSILON); values.put("K2", null); assertEquals(4.0, DataUtils.total(values), EPSILON); } @Test public void testTotal_KeyedValues3D() { DefaultKeyedValues3D data = new DefaultKeyedValues3D<>(); data.setValue(1.0, "S1", "R1", "C1"); assertEquals(1.0, DataUtils.total(data, "S1"), EPSILON); data.setValue(null, "S1", "R2", "C1"); assertEquals(1.0, DataUtils.total(data, "S1"), EPSILON); data.setValue(2.0, "S1", "R2", "C1"); assertEquals(3.0, DataUtils.total(data, "S1"), EPSILON); } @Test public void testTotal_XYZDataset() { XYZSeries s1 = new XYZSeries<>("S1"); XYZSeriesCollection dataset = new XYZSeriesCollection<>(); dataset.add(s1); assertEquals(0.0, DataUtils.total(dataset, "S1"), EPSILON); s1.add(1.0, 2.0, 3.0); assertEquals(2.0, DataUtils.total(dataset, "S1"), EPSILON); s1.add(11.0, 12.0, 13.0); assertEquals(14.0, DataUtils.total(dataset, "S1"), EPSILON); } @Test public void testStackSubTotal() { DefaultKeyedValues3D data = new DefaultKeyedValues3D<>(); double[] result = DataUtils.stackSubTotal(data, 0.0, 0, 0, 0); assertArrayEquals(result, new double[] { 0.0, 0.0 }, EPSILON); result = DataUtils.stackSubTotal(data, -1.0, 0, 0, 0); assertArrayEquals(result, new double[] { -1.0, -1.0 }, EPSILON); data.setValue(1.0, "S0", "R1", "C1"); result = DataUtils.stackSubTotal(data, 0.0, 0, 0, 0); assertArrayEquals(result, new double[] { 0.0, 0.0 }, EPSILON); result = DataUtils.stackSubTotal(data, 0.0, 1, 0, 0); assertArrayEquals(result, new double[] { 0.0, 1.0 }, EPSILON); data.setValue(2.0, "S1", "R1", "C1"); result = DataUtils.stackSubTotal(data, 0.0, 0, 0, 0); assertArrayEquals(result, new double[] { 0.0, 0.0 }, EPSILON); result = DataUtils.stackSubTotal(data, 0.0, 1, 0, 0); assertArrayEquals(result, new double[] { 0.0, 1.0 }, EPSILON); result = DataUtils.stackSubTotal(data, 0.0, 2, 0, 0); assertArrayEquals(result, new double[] { 0.0, 3.0 }, EPSILON); data.setValue(-4.0, "S2", "R1", "C1"); result = DataUtils.stackSubTotal(data, 0.0, 2, 0, 0); assertArrayEquals(result, new double[] { 0.0, 3.0 }, EPSILON); result = DataUtils.stackSubTotal(data, 0.0, 3, 0, 0); assertArrayEquals(result, new double[] { -4.0, 3.0 }, EPSILON); data.setValue(null, "S1", "R1", "C1"); result = DataUtils.stackSubTotal(data, 0.0, 3, 0, 0); assertArrayEquals(result, new double[] { -4.0, 1.0 }, EPSILON); result = DataUtils.stackSubTotal(data, 2.0, 3, 0, 0); assertArrayEquals(result, new double[] { -2.0, 3.0 }, EPSILON); } @Test public void checkExtractXYZDatasetFromColumns() { StandardCategoryDataset3D source = new StandardCategoryDataset3D<>(); source.addValue(1.0, "S1", "R1", "C1"); source.addValue(2.0, "S1", "R1", "C2"); source.addValue(3.0, "S1", "R1", "C3"); source.addValue(4.0, "S1", "R2", "C1"); source.addValue(5.0, "S1", "R2", "C2"); source.addValue(6.0, "S1", "R2", "C3"); source.addValue(11.0, "S2", "R1", "C1"); source.addValue(12.0, "S2", "R1", "C2"); source.addValue(13.0, "S2", "R1", "C3"); source.addValue(14.0, "S2", "R2", "C1"); source.addValue(15.0, "S2", "R2", "C2"); source.addValue(16.0, "S2", "R2", "C3"); XYZDataset dataset = DataUtils.extractXYZDatasetFromColumns(source, "C3", "C1", "C2"); assertEquals(2, dataset.getSeriesCount()); assertEquals("S1", dataset.getSeriesKey(0)); assertEquals("S2", dataset.getSeriesKey(1)); assertEquals(2, dataset.getItemCount(0)); assertEquals(2, dataset.getItemCount(1)); assertEquals(3.0, dataset.getX(0, 0), EPSILON); assertEquals(1.0, dataset.getY(0, 0), EPSILON); assertEquals(2.0, dataset.getZ(0, 0), EPSILON); assertEquals(6.0, dataset.getX(0, 1), EPSILON); assertEquals(4.0, dataset.getY(0, 1), EPSILON); assertEquals(5.0, dataset.getZ(0, 1), EPSILON); assertEquals(13.0, dataset.getX(1, 0), EPSILON); assertEquals(11.0, dataset.getY(1, 0), EPSILON); assertEquals(12.0, dataset.getZ(1, 0), EPSILON); assertEquals(16.0, dataset.getX(1, 1), EPSILON); assertEquals(14.0, dataset.getY(1, 1), EPSILON); assertEquals(15.0, dataset.getZ(1, 1), EPSILON); } @Test public void testFindXRange() { XYZSeries s1 = new XYZSeries<>("S1"); XYZSeriesCollection dataset = new XYZSeriesCollection<>(); dataset.add(s1); assertNull(DataUtils.findXRange(dataset)); assertNull(DataUtils.findXRange(dataset, Double.NaN)); assertNull(DataUtils.findXRange(dataset, Double.NaN, false)); assertEquals(new Range(1.0, 1.0), DataUtils.findXRange(dataset, 1.0)); assertEquals(new Range(1.0, 1.0), DataUtils.findXRange(dataset, 1.0, false)); s1.add(5.0, 6.0, 7.0); assertEquals(new Range(5.0, 5.0), DataUtils.findXRange(dataset)); assertEquals(new Range(-1.0, 5.0), DataUtils.findXRange(dataset, -1.0)); assertEquals(new Range(-1.0, 5.0), DataUtils.findXRange(dataset, -1.0, false)); s1.add(Double.NaN, 8.0, 9.0); assertEquals(new Range(5.0, 5.0), DataUtils.findXRange(dataset)); assertEquals(new Range(-1.0, 5.0), DataUtils.findXRange(dataset, -1.0)); assertEquals(new Range(-1.0, 5.0), DataUtils.findXRange(dataset, -1.0, false)); s1.add(Double.NEGATIVE_INFINITY, 8.0, 9.0); assertEquals(new Range(5.0, 5.0), DataUtils.findXRange(dataset)); assertEquals(new Range(-1.0, 5.0), DataUtils.findXRange(dataset, -1.0)); assertEquals(new Range(Double.NEGATIVE_INFINITY, 5.0), DataUtils.findXRange(dataset, -1.0, false)); s1.add(Double.POSITIVE_INFINITY, 10.0, 11.0); assertEquals(new Range(5.0, 5.0), DataUtils.findXRange(dataset)); assertEquals(new Range(-1.0, 5.0), DataUtils.findXRange(dataset, -1.0)); assertEquals(new Range(Double.NEGATIVE_INFINITY, Double.POSITIVE_INFINITY), DataUtils.findXRange(dataset, -1.0, false)); } @Test public void testFindYRange() { XYZSeries s1 = new XYZSeries<>("S1"); XYZSeriesCollection dataset = new XYZSeriesCollection<>(); dataset.add(s1); assertNull(DataUtils.findYRange(dataset)); assertNull(DataUtils.findYRange(dataset, Double.NaN)); assertNull(DataUtils.findYRange(dataset, Double.NaN, false)); assertEquals(new Range(1.0, 1.0), DataUtils.findYRange(dataset, 1.0)); assertEquals(new Range(1.0, 1.0), DataUtils.findYRange(dataset, 1.0, false)); s1.add(5.0, 6.0, 7.0); assertEquals(new Range(6.0, 6.0), DataUtils.findYRange(dataset)); assertEquals(new Range(-1.0, 6.0), DataUtils.findYRange(dataset, -1.0)); assertEquals(new Range(-1.0, 6.0), DataUtils.findYRange(dataset, -1.0, false)); s1.add(8.0, Double.NaN, 9.0); assertEquals(new Range(6.0, 6.0), DataUtils.findYRange(dataset)); assertEquals(new Range(-1.0, 6.0), DataUtils.findYRange(dataset, -1.0)); assertEquals(new Range(-1.0, 6.0), DataUtils.findYRange(dataset, -1.0, false)); s1.add(8.0, Double.NEGATIVE_INFINITY, 9.0); assertEquals(new Range(6.0, 6.0), DataUtils.findYRange(dataset)); assertEquals(new Range(-1.0, 6.0), DataUtils.findYRange(dataset, -1.0)); assertEquals(new Range(Double.NEGATIVE_INFINITY, 6.0), DataUtils.findYRange(dataset, -1.0, false)); s1.add(10.0, Double.POSITIVE_INFINITY, 11.0); assertEquals(new Range(6.0, 6.0), DataUtils.findYRange(dataset)); assertEquals(new Range(-1.0, 6.0), DataUtils.findYRange(dataset, -1.0)); assertEquals(new Range(Double.NEGATIVE_INFINITY, Double.POSITIVE_INFINITY), DataUtils.findYRange(dataset, -1.0, false)); } @Test public void testFindZRange() { XYZSeries s1 = new XYZSeries<>("S1"); XYZSeriesCollection dataset = new XYZSeriesCollection<>(); dataset.add(s1); assertNull(DataUtils.findZRange(dataset)); assertNull(DataUtils.findZRange(dataset, Double.NaN)); assertNull(DataUtils.findZRange(dataset, Double.NaN, false)); assertEquals(new Range(1.0, 1.0), DataUtils.findZRange(dataset, 1.0)); assertEquals(new Range(1.0, 1.0), DataUtils.findZRange(dataset, 1.0, false)); s1.add(5.0, 6.0, 7.0); assertEquals(new Range(7.0, 7.0), DataUtils.findZRange(dataset)); assertEquals(new Range(-1.0, 7.0), DataUtils.findZRange(dataset, -1.0)); assertEquals(new Range(-1.0, 7.0), DataUtils.findZRange(dataset, -1.0, false)); s1.add(8.0, 9.0, Double.NaN); assertEquals(new Range(7.0, 7.0), DataUtils.findZRange(dataset)); assertEquals(new Range(-1.0, 7.0), DataUtils.findZRange(dataset, -1.0)); assertEquals(new Range(-1.0, 7.0), DataUtils.findZRange(dataset, -1.0, false)); s1.add(8.0, 9.0, Double.NEGATIVE_INFINITY); assertEquals(new Range(7.0, 7.0), DataUtils.findZRange(dataset)); assertEquals(new Range(-1.0, 7.0), DataUtils.findZRange(dataset, -1.0)); assertEquals(new Range(Double.NEGATIVE_INFINITY, 7.0), DataUtils.findZRange(dataset, -1.0, false)); s1.add(10.0, 11.0, Double.POSITIVE_INFINITY); assertEquals(new Range(7.0, 7.0), DataUtils.findZRange(dataset)); assertEquals(new Range(-1.0, 7.0), DataUtils.findZRange(dataset, -1.0)); assertEquals(new Range(Double.NEGATIVE_INFINITY, Double.POSITIVE_INFINITY), DataUtils.findZRange(dataset, -1.0, false)); } } orson-charts-2.1.0/src/test/java/org/jfree/chart3d/data/DataValuesTest.java000066400000000000000000000050771417331271500265170ustar00rootroot00000000000000/* =========================================================== * Orson Charts : a 3D chart library for the Java(tm) platform * =========================================================== * * (C)opyright 2013-2022, by David Gilbert. All rights reserved. * * https://github.com/jfree/orson-charts * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . * * [Oracle and Java are registered trademarks of Oracle and/or its affiliates. * Other names may be trademarks of their respective owners.] * * If you do not wish to be bound by the terms of the GPL, an alternative * commercial license can be purchased. For details, please see visit the * Orson Charts home page: * * http://www.object-refinery.com/orsoncharts/index.html * */ package org.jfree.chart3d.data; import static org.junit.jupiter.api.Assertions.assertNull; import static org.junit.jupiter.api.Assertions.assertEquals; import org.junit.jupiter.api.Test; /** * Some checks for the {@link DataUtilities} class. */ public class DataValuesTest { @Test public void testFindValueRange() { DefaultKeyedValues3D data = new DefaultKeyedValues3D<>(); assertNull(DataUtils.findValueRange(data)); data.setValue(1.5, "S1", "R1", "C1"); assertEquals(new Range(1.5, 1.5), DataUtils.findValueRange(data)); data.setValue(-1.5, "S2", "R1", "C1"); assertEquals(new Range(-1.5, 1.5), DataUtils.findValueRange(data)); } @Test public void testFindValueRangeWithBase() { DefaultKeyedValues3D data = new DefaultKeyedValues3D<>(); assertNull(DataUtils.findValueRange(data)); data.setValue(1.5, "S1", "R1", "C1"); assertEquals(new Range(1.0, 1.5), DataUtils.findValueRange(data, 1.0)); data.setValue(-1.5, "S2", "R1", "C1"); assertEquals(new Range(-1.5, 1.5), DataUtils.findValueRange(data, 1.0)); } } orson-charts-2.1.0/src/test/java/org/jfree/chart3d/data/DefaultKeyedValueTest.java000066400000000000000000000060611417331271500300230ustar00rootroot00000000000000/* =========================================================== * Orson Charts : a 3D chart library for the Java(tm) platform * =========================================================== * * (C)opyright 2013-2022, by David Gilbert. All rights reserved. * * https://github.com/jfree/orson-charts * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . * * [Oracle and Java are registered trademarks of Oracle and/or its affiliates. * Other names may be trademarks of their respective owners.] * * If you do not wish to be bound by the terms of the GPL, an alternative * commercial license can be purchased. For details, please see visit the * Orson Charts home page: * * http://www.object-refinery.com/orsoncharts/index.html * */ package org.jfree.chart3d.data; import org.jfree.chart3d.TestUtils; import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertFalse; import static org.junit.jupiter.api.Assertions.assertTrue; import org.junit.jupiter.api.Test; /** * Some checks for the {@link DefaultKeyedValue} class. */ public class DefaultKeyedValueTest { @Test public void testEquals() { DefaultKeyedValue kv1 = new DefaultKeyedValue<>("K1", Double.valueOf(1.0)); DefaultKeyedValue kv2 = new DefaultKeyedValue<>("K1", 1.0); assertEquals(kv1, kv2); assertFalse(kv1.equals(null)); kv1 = new DefaultKeyedValue<>("K2", 1.0); assertFalse(kv1.equals(kv2)); kv2 = new DefaultKeyedValue<>("K2", 1.0); assertTrue(kv1.equals(kv2)); kv1 = new DefaultKeyedValue<>("K2", 2.0); assertFalse(kv1.equals(kv2)); kv2 = new DefaultKeyedValue<>("K2", 2.0); assertTrue(kv1.equals(kv2)); kv1 = new DefaultKeyedValue<>("K2", null); assertFalse(kv1.equals(kv2)); kv2 = new DefaultKeyedValue<>("K2", null); assertTrue(kv1.equals(kv2)); } @Test @SuppressWarnings("unchecked") public void testSerialization() { DefaultKeyedValue kv1 = new DefaultKeyedValue<>("K1", 1.0); DefaultKeyedValue kv2 = (DefaultKeyedValue) TestUtils.serialized(kv1); assertTrue(kv1.equals(kv2)); kv1 = new DefaultKeyedValue<>("K1", null); kv2 = (DefaultKeyedValue) TestUtils.serialized(kv1); assertTrue(kv1.equals(kv2)); } } orson-charts-2.1.0/src/test/java/org/jfree/chart3d/data/DefaultKeyedValues2DTest.java000066400000000000000000000117331417331271500303760ustar00rootroot00000000000000/* =========================================================== * Orson Charts : a 3D chart library for the Java(tm) platform * =========================================================== * * (C)opyright 2013-2022, by David Gilbert. All rights reserved. * * https://github.com/jfree/orson-charts * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . * * [Oracle and Java are registered trademarks of Oracle and/or its affiliates. * Other names may be trademarks of their respective owners.] * * If you do not wish to be bound by the terms of the GPL, an alternative * commercial license can be purchased. For details, please see visit the * Orson Charts home page: * * http://www.object-refinery.com/orsoncharts/index.html * */ package org.jfree.chart3d.data; import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertTrue; import static org.junit.jupiter.api.Assertions.assertFalse; import static org.junit.jupiter.api.Assertions.assertNull; import org.junit.jupiter.api.Test; import org.jfree.chart3d.TestUtils; /** * Some checks for the {@link DefaultKeyedValues2D} class. */ public class DefaultKeyedValues2DTest { private static final double EPSILON = 0.00000001; @Test public void testGetValue() { DefaultKeyedValues2D kv2d = new DefaultKeyedValues2D<>(); kv2d.setValue(1.0, "R1", "C1"); kv2d.setValue(2.0, "R1", "C2"); kv2d.setValue(3.0, "R1", "C3"); kv2d.setValue(4.0, "R2", "C1"); kv2d.setValue(5.0, "R2", "C2"); kv2d.setValue(6.0, "R2", "C3"); assertEquals(1.0, kv2d.getValue("R1", "C1")); assertEquals(2.0, kv2d.getValue("R1", "C2")); assertEquals(3.0, kv2d.getValue("R1", "C3")); assertEquals(4.0, kv2d.getValue("R2", "C1")); assertEquals(5.0, kv2d.getValue("R2", "C2")); assertEquals(6.0, kv2d.getValue("R2", "C3")); } @Test public void testSetValue() { // empty data DefaultKeyedValues2D data = new DefaultKeyedValues2D<>(); data.setValue(1.0, "R1", "C1"); assertEquals(1.0, data.getValue("R1", "C1").doubleValue(), EPSILON); assertEquals(1, data.getRowCount()); assertEquals(1, data.getColumnCount()); // existing keys data.setValue(2.0, "R1", "C1"); assertEquals(2.0, data.getValue("R1", "C1").doubleValue(), EPSILON); assertEquals(1, data.getRowCount()); assertEquals(1, data.getColumnCount()); // existing row key, new column key data.setValue(3.0, "R1", "C2"); assertEquals(3.0, data.getValue("R1", "C2").doubleValue(), EPSILON); assertEquals(1, data.getRowCount()); assertEquals(2, data.getColumnCount()); // existing column key, new row key data.setValue(4.0, "R2", "C2"); assertEquals(4.0, data.getValue("R2", "C2").doubleValue(), EPSILON); assertEquals(2, data.getRowCount()); assertEquals(2, data.getColumnCount()); assertNull(data.getValue("R2", "C1")); // new row key and new column key data.setValue(5.0, "R3", "C3"); assertEquals(5.0, data.getValue("R3", "C3").doubleValue(), EPSILON); assertEquals(3, data.getRowCount()); assertEquals(3, data.getColumnCount()); assertNull(data.getValue("R1", "C3")); } @Test public void testEquals() { DefaultKeyedValues2D d1 = new DefaultKeyedValues2D<>(); DefaultKeyedValues2D d2 = new DefaultKeyedValues2D<>(); assertTrue(d1.equals(d2)); assertFalse(d1.equals(null)); d1.setValue(1.0, "R1", "C1"); assertFalse(d1.equals(d2)); d2.setValue(1.0, "R1", "C1"); assertTrue(d1.equals(d2)); } /** * Check for serialization support. */ @Test @SuppressWarnings("unchecked") public void testSerialization() { DefaultKeyedValues2D d1 = new DefaultKeyedValues2D<>(); d1.setValue(1.0, "R1", "C1"); DefaultKeyedValues2D d2 = (DefaultKeyedValues2D) TestUtils.serialized(d1); assertEquals(d1, d2); } } orson-charts-2.1.0/src/test/java/org/jfree/chart3d/data/DefaultKeyedValues3DTest.java000066400000000000000000000152541417331271500304010ustar00rootroot00000000000000/* =========================================================== * Orson Charts : a 3D chart library for the Java(tm) platform * =========================================================== * * (C)opyright 2013-2022, by David Gilbert. All rights reserved. * * https://github.com/jfree/orson-charts * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . * * [Oracle and Java are registered trademarks of Oracle and/or its affiliates. * Other names may be trademarks of their respective owners.] * * If you do not wish to be bound by the terms of the GPL, an alternative * commercial license can be purchased. For details, please see visit the * Orson Charts home page: * * http://www.object-refinery.com/orsoncharts/index.html * */ package org.jfree.chart3d.data; import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertFalse; import static org.junit.jupiter.api.Assertions.assertTrue; import static org.junit.jupiter.api.Assertions.assertNull; import org.junit.jupiter.api.Test; import org.jfree.chart3d.TestUtils; /** * Some tests for the {@link DefaultKeyedValues3D} class. */ public class DefaultKeyedValues3DTest { private static final double EPSILON = 0.000000001; @Test public void testSetValue() { DefaultKeyedValues3D data = new DefaultKeyedValues3D<>(); // adding to an empty dataset... data.setValue(1.0, "S1", "R1", "C1"); assertEquals(1.0, data.getValue("S1", "R1", "C1").doubleValue(), EPSILON); assertEquals(1, data.getSeriesCount()); assertEquals(1, data.getRowCount()); assertEquals(1, data.getColumnCount()); // updating the existing value... data.setValue(2.0, "S1", "R1", "C1"); assertEquals(2.0, data.getValue("S1", "R1", "C1").doubleValue(), EPSILON); assertEquals(1, data.getSeriesCount()); assertEquals(1, data.getRowCount()); assertEquals(1, data.getColumnCount()); // row and column exist, but creating a new series data.setValue(3.0, "S2", "R1", "C1"); assertEquals(3.0, data.getValue("S2", "R1", "C1").doubleValue(), EPSILON); assertEquals(2, data.getSeriesCount()); assertEquals(1, data.getRowCount()); assertEquals(1, data.getColumnCount()); assertEquals(2.0, data.getValue("S1", "R1", "C1")); // series and row exists, but column does not data.setValue(4.0, "S2", "R1", "C2"); assertEquals(4.0, data.getValue("S2", "R1", "C2").doubleValue(), EPSILON); assertEquals(2, data.getSeriesCount()); assertEquals(1, data.getRowCount()); assertEquals(2, data.getColumnCount()); assertNull(data.getValue("S1", "R1", "C2")); // row exists, but series an column do not data.setValue(5.0, "S3", "R1", "C3"); assertEquals(5.0, data.getValue("S3", "R1", "C3").doubleValue(), EPSILON); assertEquals(3, data.getSeriesCount()); assertEquals(1, data.getRowCount()); assertEquals(3, data.getColumnCount()); assertNull(data.getValue("S1", "R1", "C3")); assertNull(data.getValue("S2", "R1", "C3")); // series and column exists, but row does not data.setValue(6.0, "S1", "R2", "C1"); assertEquals(6.0, data.getValue("S1", "R2", "C1").doubleValue(), EPSILON); assertEquals(3, data.getSeriesCount()); assertEquals(2, data.getRowCount()); assertEquals(3, data.getColumnCount()); assertNull(data.getValue("S2", "R2", "C1")); assertNull(data.getValue("S3", "R2", "C1")); // column exists, but series and row does not data.setValue(7.0, "S4", "R3", "C1"); assertEquals(7.0, data.getValue("S4", "R3", "C1").doubleValue(), EPSILON); assertEquals(4, data.getSeriesCount()); assertEquals(3, data.getRowCount()); assertEquals(3, data.getColumnCount()); assertNull(data.getValue("S1", "R3", "C1")); assertNull(data.getValue("S2", "R3", "C1")); assertNull(data.getValue("S3", "R3", "C1")); // series exists, but row and column does not data.setValue(8.0, "S1", "R4", "C4"); assertEquals(8.0, data.getValue("S1", "R4", "C4").doubleValue(), EPSILON); assertEquals(4, data.getSeriesCount()); assertEquals(4, data.getRowCount()); assertEquals(4, data.getColumnCount()); assertNull(data.getValue("S2", "R4", "C4")); assertNull(data.getValue("S3", "R4", "C4")); assertNull(data.getValue("S4", "R4", "C4")); // series, row and column does not exist data.setValue(9.0, "S5", "R5", "C5"); assertEquals(9.0, data.getValue("S5", "R5", "C5").doubleValue(), EPSILON); assertEquals(5, data.getSeriesCount()); assertEquals(5, data.getRowCount()); assertEquals(5, data.getColumnCount()); assertNull(data.getValue("S1", "R5", "C5")); } @Test public void testEquals() { DefaultKeyedValues3D d1 = new DefaultKeyedValues3D<>(); DefaultKeyedValues3D d2 = new DefaultKeyedValues3D<>(); assertTrue(d1.equals(d2)); assertFalse(d1.equals(null)); d1.setValue(1.0, "S1", "R1", "C1"); assertFalse(d1.equals(d2)); d2.setValue(1.0, "S1", "R1", "C1"); assertTrue(d1.equals(d2)); } /** * Check for serialization support. */ @Test @SuppressWarnings("unchecked") public void testSerialization() { DefaultKeyedValues3D d1 = new DefaultKeyedValues3D<>(); d1.setValue(1.0, "S1", "R1", "C1"); DefaultKeyedValues3D d2 = (DefaultKeyedValues3D) TestUtils.serialized(d1); assertEquals(d1, d2); } } orson-charts-2.1.0/src/test/java/org/jfree/chart3d/data/DefaultKeyedValuesTest.java000066400000000000000000000057171417331271500302150ustar00rootroot00000000000000/* =========================================================== * Orson Charts : a 3D chart library for the Java(tm) platform * =========================================================== * * (C)opyright 2013-2022, by David Gilbert. All rights reserved. * * https://github.com/jfree/orson-charts * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . * * [Oracle and Java are registered trademarks of Oracle and/or its affiliates. * Other names may be trademarks of their respective owners.] * * If you do not wish to be bound by the terms of the GPL, an alternative * commercial license can be purchased. For details, please see visit the * Orson Charts home page: * * http://www.object-refinery.com/orsoncharts/index.html * */ package org.jfree.chart3d.data; import static org.junit.jupiter.api.Assertions.assertFalse; import static org.junit.jupiter.api.Assertions.assertNull; import static org.junit.jupiter.api.Assertions.assertTrue; import org.junit.jupiter.api.Test; import org.jfree.chart3d.TestUtils; /** * Tests for the {@link DefaultKeyedValues} class. */ public class DefaultKeyedValuesTest { /** * Check for getValue(key) where key is not in the data structure (was * failing at one time). */ @Test public void testGetValueForNonExistentKey() { DefaultKeyedValues kv1 = new DefaultKeyedValues<>(); assertNull(kv1.getValue("ABC")); } @Test public void testEquals() { DefaultKeyedValues kv1 = new DefaultKeyedValues<>(); DefaultKeyedValues kv2 = new DefaultKeyedValues<>(); assertTrue(kv1.equals(kv2)); assertFalse(kv1.equals(null)); kv1.put("A", 1.0); assertFalse(kv1.equals(kv2)); kv2.put("A", 1.0); assertTrue(kv1.equals(kv2)); kv1.put("B", null); assertFalse(kv1.equals(kv2)); kv2.put("B", null); assertTrue(kv1.equals(kv2)); } @Test @SuppressWarnings("unchecked") public void testSerialization() { DefaultKeyedValues kv1 = new DefaultKeyedValues<>(); kv1.put("A", 1.0); kv1.put("B", 2.0); kv1.put("C", null); DefaultKeyedValues kv2 = (DefaultKeyedValues) TestUtils.serialized(kv1); assertTrue(kv1.equals(kv2)); } } orson-charts-2.1.0/src/test/java/org/jfree/chart3d/data/JSONUtilsTest.java000066400000000000000000000246651417331271500262640ustar00rootroot00000000000000/* =========================================================== * Orson Charts : a 3D chart library for the Java(tm) platform * =========================================================== * * (C)opyright 2013-2022, by David Gilbert. All rights reserved. * * https://github.com/jfree/orson-charts * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . * * [Oracle and Java are registered trademarks of Oracle and/or its affiliates. * Other names may be trademarks of their respective owners.] * * If you do not wish to be bound by the terms of the GPL, an alternative * commercial license can be purchased. For details, please see visit the * Orson Charts home page: * * http://www.object-refinery.com/orsoncharts/index.html * */ package org.jfree.chart3d.data; import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertNull; import static org.junit.jupiter.api.Assertions.assertTrue; import org.junit.jupiter.api.Test; import org.jfree.chart3d.data.category.StandardCategoryDataset3D; import org.jfree.chart3d.data.xyz.XYZDataset; import org.jfree.chart3d.data.xyz.XYZSeries; import org.jfree.chart3d.data.xyz.XYZSeriesCollection; /** * Some tests for the {@link JSONUtils} class. */ public class JSONUtilsTest { /** * Some checks for the readKeyedValues() method. */ @Test public void checkReadKeyedValues() { String json = "[]"; KeyedValues dkv = JSONUtils.readKeyedValues(json); assertTrue(dkv.getItemCount() == 0); json = "[[\"Key 1\", 1.23], [\"Key 2\", null], [\"NaN\", null], " + "[\"MIN_VALUE\", 4.9E-324], " + "[\"MAX_VALUE\", 1.7976931348623157E308], " + "[\"POSITIVE_INFINITY\", null]]"; dkv = JSONUtils.readKeyedValues(json); assertTrue(dkv.getItemCount() == 6); assertEquals(1.23, dkv.getValue("Key 1")); assertEquals(1.23, dkv.getValue(0)); assertNull(dkv.getValue("Key 2")); assertNull(dkv.getValue(1)); assertNull(dkv.getValue("NaN")); assertNull(dkv.getValue(2)); assertEquals(Double.MIN_VALUE, dkv.getValue("MIN_VALUE")); assertEquals(Double.MIN_VALUE, dkv.getValue(3)); assertEquals(Double.MAX_VALUE, dkv.getValue("MAX_VALUE")); assertEquals(Double.MAX_VALUE, dkv.getValue(4)); assertNull(dkv.getValue("POSITIVE_INFINITY")); assertNull(dkv.getValue(5)); } @Test public void checkWriteKeyedValues() { // some standard cases are already checked in the tests for the // toString() method in StandardPieDataset3D DefaultKeyedValues dkv = new DefaultKeyedValues<>(); dkv.put("\"", 1.0); assertEquals("[[\"\\\"\", 1.0]]", JSONUtils.writeKeyedValues(dkv)); dkv.clear(); dkv.put("\\", 1.0); assertEquals("[[\"\\\\\", 1.0]]", JSONUtils.writeKeyedValues(dkv)); dkv.clear(); dkv.put("\t", 1.0); assertEquals("[[\"\\t\", 1.0]]", JSONUtils.writeKeyedValues(dkv)); dkv.clear(); dkv.put("\n", 1.0); assertEquals("[[\"\\n\", 1.0]]", JSONUtils.writeKeyedValues(dkv)); dkv.clear(); dkv.put("\f", 1.0); assertEquals("[[\"\\f\", 1.0]]", JSONUtils.writeKeyedValues(dkv)); dkv.clear(); dkv.put("\b", 1.0); assertEquals("[[\"\\b\", 1.0]]", JSONUtils.writeKeyedValues(dkv)); dkv.clear(); dkv.put("\r", 1.0); assertEquals("[[\"\\r\", 1.0]]", JSONUtils.writeKeyedValues(dkv)); dkv.clear(); dkv.put("/", 1.0); assertEquals("[[\"\\/\", 1.0]]", JSONUtils.writeKeyedValues(dkv)); dkv.clear(); } @Test public void checkReadKeyedValues2D() { String json = "{}"; KeyedValues2D dkv2d = JSONUtils.readKeyedValues2D(json); assertEquals(0, dkv2d.getRowCount()); assertEquals(0, dkv2d.getColumnCount()); json = "{\"columnKeys\": [\"C1\", \"C2\", \"C3\"], \"rows\": " + "[[\"R1\", [1.0, 2.0, 3.0]], [\"R2\", [4.0, 5.0, 6.0]]]}"; dkv2d = JSONUtils.readKeyedValues2D(json); assertEquals(2, dkv2d.getRowCount()); assertEquals(3, dkv2d.getColumnCount()); assertEquals(1.0, dkv2d.getValue("R1", "C1")); assertEquals(2.0, dkv2d.getValue("R1", "C2")); assertEquals(3.0, dkv2d.getValue("R1", "C3")); assertEquals(4.0, dkv2d.getValue("R2", "C1")); assertEquals(5.0, dkv2d.getValue("R2", "C2")); assertEquals(6.0, dkv2d.getValue("R2", "C3")); } @Test public void checkWriteKeyedValues2D() { DefaultKeyedValues2D dkv2d = new DefaultKeyedValues2D<>(); String expected = "{}"; assertEquals(expected, JSONUtils.writeKeyedValues2D(dkv2d)); dkv2d.setValue(1.0, "R1", "C1"); expected = "{\"columnKeys\": [\"C1\"], \"rows\": [[\"R1\", [1.0]]]}"; assertEquals(expected, JSONUtils.writeKeyedValues2D(dkv2d)); } @Test public void checkReadKeyedValues3D() { String json = "{}"; KeyedValues3D dkv3d = JSONUtils.readKeyedValues3D(json); assertEquals(0, dkv3d.getRowCount()); assertEquals(0, dkv3d.getColumnCount()); json = "{\"columnKeys\": [\"C1\", \"C2\"], \"rowKeys\": " + "[\"R1\", \"R2\"], \"data\": [{\"seriesKey\": \"S1\", " + "\"rows\": {\"R1\": [1.0, 2.0], \"R2\": [3.0, 4.0]}}, " + "{\"seriesKey\": \"S2\", \"rows\": {\"R2\": [5.0, 6.0]}}]}"; dkv3d = JSONUtils.readKeyedValues3D(json); assertEquals(2, dkv3d.getSeriesCount()); assertEquals("S1", dkv3d.getSeriesKey(0)); assertEquals("S2", dkv3d.getSeriesKey(1)); assertEquals(2, dkv3d.getRowCount()); assertEquals("R1", dkv3d.getRowKey(0)); assertEquals("R2", dkv3d.getRowKey(1)); assertEquals(2, dkv3d.getColumnCount()); assertEquals("C1", dkv3d.getColumnKey(0)); assertEquals("C2", dkv3d.getColumnKey(1)); assertEquals(1.0, dkv3d.getValue("S1", "R1", "C1")); assertEquals(2.0, dkv3d.getValue("S1", "R1", "C2")); assertEquals(3.0, dkv3d.getValue("S1", "R2", "C1")); assertEquals(4.0, dkv3d.getValue("S1", "R2", "C2")); assertEquals(5.0, dkv3d.getValue("S2", "R2", "C1")); assertEquals(6.0, dkv3d.getValue("S2", "R2", "C2")); } @Test public void checkWriteKeyedValues3D() { StandardCategoryDataset3D dataset = new StandardCategoryDataset3D<>(); dataset.addValue(1.0, "S1", "R1", "C1"); dataset.addValue(2.0, "S1", "R1", "C2"); dataset.addValue(3.0, "S1", "R2", "C1"); dataset.addValue(4.0, "S1", "R2", "C2"); // series 2 only has data in row 2 dataset.addValue(5.0, "S2", "R2", "C1"); dataset.addValue(6.0, "S2", "R2", "C2"); String expected = "{\"columnKeys\": [\"C1\", \"C2\"], \"rowKeys\": " + "[\"R1\", \"R2\"], \"series\": [{\"seriesKey\": \"S1\", " + "\"rows\": [[\"R1\", [1.0, 2.0]], [\"R2\", [3.0, 4.0]]]}, " + "{\"seriesKey\": \"S2\", \"rows\": [[\"R2\", [5.0, 6.0]]]}]}"; assertEquals(expected, JSONUtils.writeKeyedValues3D(dataset)); } private static final double EPSILON = 0.0000001; /** * Tests for reading XYZDatasets from JSON format. */ @Test public void checkReadXYZDataset() { String json = "[]"; XYZDataset dataset = JSONUtils.readXYZDataset(json); assertEquals(0, dataset.getSeriesCount()); json = "[[\"Series 1\", [[1.0, 2.0, 3.0], [4.0, 5.0, 6.0]]], " + "[\"Series 2\", [[5.5, 6.6, 7.7], [8.8, 9.9, 9.9], " + "[8.4, 9.2, 9.1]]]]"; dataset = JSONUtils.readXYZDataset(json); assertEquals(2, dataset.getSeriesCount()); assertEquals("Series 1", dataset.getSeriesKey(0)); assertEquals("Series 2", dataset.getSeriesKey(1)); assertEquals(2, dataset.getItemCount(0)); assertEquals(3, dataset.getItemCount(1)); assertEquals(1.0, dataset.getX(0, 0), EPSILON); assertEquals(2.0, dataset.getY(0, 0), EPSILON); assertEquals(3.0, dataset.getZ(0, 0), EPSILON); assertEquals(4.0, dataset.getX(0, 1), EPSILON); assertEquals(5.0, dataset.getY(0, 1), EPSILON); assertEquals(6.0, dataset.getZ(0, 1), EPSILON); assertEquals(5.5, dataset.getX(1, 0), EPSILON); assertEquals(6.6, dataset.getY(1, 0), EPSILON); assertEquals(7.7, dataset.getZ(1, 0), EPSILON); assertEquals(8.8, dataset.getX(1, 1), EPSILON); assertEquals(9.9, dataset.getY(1, 1), EPSILON); assertEquals(9.9, dataset.getZ(1, 1), EPSILON); assertEquals(8.4, dataset.getX(1, 2), EPSILON); assertEquals(9.2, dataset.getY(1, 2), EPSILON); assertEquals(9.1, dataset.getZ(1, 2), EPSILON); } /** * Tests for writing XYZDatasets to JSON format. */ @Test public void checkWriteXYZDataset() { XYZSeriesCollection dataset = new XYZSeriesCollection<>(); assertEquals("[]", JSONUtils.writeXYZDataset(dataset)); XYZSeries s1 = new XYZSeries<>("S1"); dataset.add(s1); assertEquals("[[\"S1\", []]]", JSONUtils.writeXYZDataset(dataset)); s1.add(1.0, 2.0, 3.0); assertEquals("[[\"S1\", [[1.0, 2.0, 3.0]]]]", JSONUtils.writeXYZDataset(dataset)); XYZSeries s2 = new XYZSeries<>("S2"); dataset.add(s2); assertEquals("[[\"S1\", [[1.0, 2.0, 3.0]]], [\"S2\", []]]", JSONUtils.writeXYZDataset(dataset)); } } orson-charts-2.1.0/src/test/java/org/jfree/chart3d/data/KeyedValues3DItemKeyTest.java000066400000000000000000000055521417331271500303640ustar00rootroot00000000000000/* =========================================================== * Orson Charts : a 3D chart library for the Java(tm) platform * =========================================================== * * (C)opyright 2013-2022, by David Gilbert. All rights reserved. * * https://github.com/jfree/orson-charts * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . * * [Oracle and Java are registered trademarks of Oracle and/or its affiliates. * Other names may be trademarks of their respective owners.] * * If you do not wish to be bound by the terms of the GPL, an alternative * commercial license can be purchased. For details, please see visit the * Orson Charts home page: * * http://www.object-refinery.com/orsoncharts/index.html * */ package org.jfree.chart3d.data; import static org.junit.jupiter.api.Assertions.assertFalse; import static org.junit.jupiter.api.Assertions.assertTrue; import org.junit.jupiter.api.Test; import org.jfree.chart3d.TestUtils; /** * Tests for the {@link KeyedValues3DItemKey} class. */ public class KeyedValues3DItemKeyTest { @Test public void testEquals() { KeyedValues3DItemKey k1 = new KeyedValues3DItemKey<>("A", "B", "C"); KeyedValues3DItemKey k2 = new KeyedValues3DItemKey<>("A", "B", "C"); assertTrue(k1.equals(k2)); assertFalse(k1.equals(null)); k1 = new KeyedValues3DItemKey<>("AA", "B", "C"); assertFalse(k1.equals(k2)); k2 = new KeyedValues3DItemKey<>("AA", "B", "C"); assertTrue(k1.equals(k2)); k1 = new KeyedValues3DItemKey<>("AA", "BB", "C"); assertFalse(k1.equals(k2)); k2 = new KeyedValues3DItemKey<>("AA", "BB", "C"); assertTrue(k1.equals(k2)); k1 = new KeyedValues3DItemKey<>("AA", "BB", "CC"); assertFalse(k1.equals(k2)); k2 = new KeyedValues3DItemKey<>("AA", "BB", "CC"); assertTrue(k1.equals(k2)); } @Test public void testSerialization() { KeyedValues3DItemKey k1 = new KeyedValues3DItemKey<>("A", "B", "C"); KeyedValues3DItemKey k2 = (KeyedValues3DItemKey) TestUtils.serialized(k1); assertTrue(k1.equals(k2)); } } orson-charts-2.1.0/src/test/java/org/jfree/chart3d/data/KeyedValuesItemKeyTest.java000066400000000000000000000044461417331271500301760ustar00rootroot00000000000000/* =========================================================== * Orson Charts : a 3D chart library for the Java(tm) platform * =========================================================== * * (C)opyright 2013-2022, by David Gilbert. All rights reserved. * * https://github.com/jfree/orson-charts * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . * * [Oracle and Java are registered trademarks of Oracle and/or its affiliates. * Other names may be trademarks of their respective owners.] * * If you do not wish to be bound by the terms of the GPL, an alternative * commercial license can be purchased. For details, please see visit the * Orson Charts home page: * * http://www.object-refinery.com/orsoncharts/index.html * */ package org.jfree.chart3d.data; import static org.junit.jupiter.api.Assertions.assertFalse; import static org.junit.jupiter.api.Assertions.assertTrue; import org.junit.jupiter.api.Test; import org.jfree.chart3d.TestUtils; /** * Tests for the {@link KeyedValuesItemKey} class. */ public class KeyedValuesItemKeyTest { @Test public void testEquals() { KeyedValuesItemKey k1 = new KeyedValuesItemKey("A"); KeyedValuesItemKey k2 = new KeyedValuesItemKey("A"); assertTrue(k1.equals(k2)); assertFalse(k1.equals(null)); k1 = new KeyedValuesItemKey("AA"); assertFalse(k1.equals(k2)); k2 = new KeyedValuesItemKey("AA"); assertTrue(k1.equals(k2)); } @Test public void testSerialization() { KeyedValuesItemKey k1 = new KeyedValuesItemKey("A"); KeyedValuesItemKey k2 = (KeyedValuesItemKey) TestUtils.serialized(k1); assertTrue(k1.equals(k2)); } } orson-charts-2.1.0/src/test/java/org/jfree/chart3d/data/RangeTest.java000066400000000000000000000062201417331271500255110ustar00rootroot00000000000000/* =========================================================== * Orson Charts : a 3D chart library for the Java(tm) platform * =========================================================== * * (C)opyright 2013-2022, by David Gilbert. All rights reserved. * * https://github.com/jfree/orson-charts * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . * * [Oracle and Java are registered trademarks of Oracle and/or its affiliates. * Other names may be trademarks of their respective owners.] * * If you do not wish to be bound by the terms of the GPL, an alternative * commercial license can be purchased. For details, please see visit the * Orson Charts home page: * * http://www.object-refinery.com/orsoncharts/index.html * */ package org.jfree.chart3d.data; import org.jfree.chart3d.TestUtils; import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertFalse; import static org.junit.jupiter.api.Assertions.assertNotEquals; import static org.junit.jupiter.api.Assertions.assertTrue; import org.junit.jupiter.api.Test; /** * Some tests for the {@link Range} class. */ public class RangeTest { @Test public void testEquals() { Range range1 = new Range(0, 10); Range range2 = new Range(0, 10); assertEquals(range1, range2); range1 = new Range(2, 4); assertNotEquals(range1, range2); range2 = new Range(2, 4); assertEquals(range1, range2); } @Test public void testContains() { Range r = new Range(0, 10); assertFalse(r.contains(-0.5)); assertTrue(r.contains(0.0)); assertTrue(r.contains(5.0)); assertTrue(r.contains(10.0)); assertFalse(r.contains(10.5)); } @Test public void testIntersects() { Range r = new Range(0, 10); assertFalse(r.intersects(-0.5, -0.1)); assertTrue(r.intersects(-0.5, 0.0)); assertTrue(r.intersects(0.0, 5.0)); assertTrue(r.intersects(0.0, 10.0)); assertTrue(r.intersects(0.0, 11.0)); assertTrue(r.intersects(5.0, 9.0)); assertTrue(r.intersects(5.0, 10.0)); assertTrue(r.intersects(5.0, 11.0)); assertTrue(r.intersects(10.0, 11.0)); assertFalse(r.intersects(10.5, 11.0)); } private static final double EPSILON = 0.0000001; /** * A check for serialization. */ @Test public void testSerialization() { Range r1 = new Range(0, 10); Range r2 = (Range) TestUtils.serialized(r1); assertEquals(r1, r2); } } orson-charts-2.1.0/src/test/java/org/jfree/chart3d/data/StandardPieDataset3DTest.java000066400000000000000000000072521417331271500303560ustar00rootroot00000000000000/* =========================================================== * Orson Charts : a 3D chart library for the Java(tm) platform * =========================================================== * * (C)opyright 2013-2022, by David Gilbert. All rights reserved. * * https://github.com/jfree/orson-charts * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . * * [Oracle and Java are registered trademarks of Oracle and/or its affiliates. * Other names may be trademarks of their respective owners.] * * If you do not wish to be bound by the terms of the GPL, an alternative * commercial license can be purchased. For details, please see visit the * Orson Charts home page: * * http://www.object-refinery.com/orsoncharts/index.html * */ package org.jfree.chart3d.data; import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertFalse; import static org.junit.jupiter.api.Assertions.assertTrue; import org.junit.jupiter.api.Test; import org.jfree.chart3d.TestUtils; /** * Tests for the {@link StandardPieDataset} class. */ public class StandardPieDataset3DTest { @Test public void testGeneral() { StandardPieDataset3D d1 = new StandardPieDataset3D<>(); assertTrue(d1.isNotify()); } @Test public void testEquals() { StandardPieDataset3D d1 = new StandardPieDataset3D<>(); StandardPieDataset3D d2 = new StandardPieDataset3D<>(); assertTrue(d1.equals(d2)); assertFalse(d1.equals(null)); d1.add("K1", 1.0); assertFalse(d1.equals(d2)); d2.add("K1", 1.0); assertTrue(d1.equals(d2)); d1.add("K2", null); assertFalse(d1.equals(d2)); d2.add("K2", null); assertTrue(d1.equals(d2)); } @Test @SuppressWarnings("unchecked") public void testSerialization() { StandardPieDataset3D d1 = new StandardPieDataset3D<>(); StandardPieDataset3D d2 = (StandardPieDataset3D) TestUtils.serialized(d1); assertTrue(d1.equals(d2)); d1.add("K1", 1.0); d2 = (StandardPieDataset3D) TestUtils.serialized(d1); assertTrue(d1.equals(d2)); d1.add("K2", null); d2 = (StandardPieDataset3D) TestUtils.serialized(d1); assertTrue(d1.equals(d2)); } /** * Checks for the toString() method. Since this uses the * {@link JSONUtils#writeKeyedValues3DToJSON(org.jfree.chart3d.data.KeyedValues3D)} * method, we are really checking the JSON conversion. */ @Test public void checkToString() { StandardPieDataset3D dataset = new StandardPieDataset3D<>(); assertEquals("[]", dataset.toString()); dataset.add("key", 1.0); assertEquals("[[\"key\", 1.0]]", dataset.toString()); dataset.add("key", null); assertEquals("[[\"key\", null]]", dataset.toString()); dataset.add("another key", 2.0); assertEquals("[[\"key\", null], [\"another key\", 2.0]]", dataset.toString()); } } orson-charts-2.1.0/src/test/java/org/jfree/chart3d/data/category/000077500000000000000000000000001417331271500245675ustar00rootroot00000000000000orson-charts-2.1.0/src/test/java/org/jfree/chart3d/data/category/StandardCategoryDataset3DTest.java000066400000000000000000000115231417331271500332270ustar00rootroot00000000000000/* =========================================================== * Orson Charts : a 3D chart library for the Java(tm) platform * =========================================================== * * (C)opyright 2013-2022, by David Gilbert. All rights reserved. * * https://github.com/jfree/orson-charts * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . * * [Oracle and Java are registered trademarks of Oracle and/or its affiliates. * Other names may be trademarks of their respective owners.] * * If you do not wish to be bound by the terms of the GPL, an alternative * commercial license can be purchased. For details, please see visit the * Orson Charts home page: * * http://www.object-refinery.com/orsoncharts/index.html * */ package org.jfree.chart3d.data.category; import org.jfree.chart3d.TestUtils; import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertFalse; import static org.junit.jupiter.api.Assertions.assertTrue; import org.junit.jupiter.api.Test; /** * Tests for the {@link StandardCategoryDataset3D} class. */ public class StandardCategoryDataset3DTest { @Test public void checkGeneral() { StandardCategoryDataset3D dataset = new StandardCategoryDataset3D(); assertEquals(0, dataset.getSeriesCount()); assertEquals(0, dataset.getRowCount()); assertEquals(0, dataset.getColumnCount()); assertTrue(dataset.getSeriesKeys().isEmpty()); assertTrue(dataset.getRowKeys().isEmpty()); assertTrue(dataset.getColumnKeys().isEmpty()); assertTrue(dataset.isNotify()); } @Test public void checkEquals() { StandardCategoryDataset3D d1 = new StandardCategoryDataset3D<>(); StandardCategoryDataset3D d2 = new StandardCategoryDataset3D<>(); assertTrue(d1.equals(d2)); assertFalse(d1.equals(null)); d1.addValue(1.0, "S1", "R1", "C1"); assertFalse(d1.equals(d2)); d2.addValue(1.0, "S1", "R1", "C1"); assertTrue(d1.equals(d2)); d1.addValue(null, "S1", "R2", "C2"); assertFalse(d1.equals(d2)); d2.addValue(null, "S1", "R2", "C2"); assertTrue(d1.equals(d2)); } /** * A check for serialization. */ @Test @SuppressWarnings("unchecked") public void checkSerialization() { StandardCategoryDataset3D d1 = new StandardCategoryDataset3D<>(); d1.addValue(1.0, "S1", "R1", "C1"); StandardCategoryDataset3D d2 = (StandardCategoryDataset3D) TestUtils.serialized(d1); assertEquals(d1, d2); } @Test public void checkToString() { StandardCategoryDataset3D dataset = new StandardCategoryDataset3D<>(); assertEquals("{}", dataset.toString()); dataset.addValue(1.0, "S1", "R1", "C1"); assertEquals("{\"columnKeys\": [\"C1\"], \"rowKeys\": [\"R1\"], " + "\"series\": [{\"seriesKey\": \"S1\", " + "\"rows\": [[\"R1\", [1.0]]]}]}", dataset.toString()); dataset.addValue(2.0, "S1", "R1", "C2"); assertEquals("{\"columnKeys\": [\"C1\", \"C2\"], \"rowKeys\": [\"R1\"], " + "\"series\": [{\"seriesKey\": \"S1\", " + "\"rows\": [[\"R1\", [1.0, 2.0]]]}]}", dataset.toString()); dataset.addValue(3.0, "S1", "R2", "C2"); assertEquals("{\"columnKeys\": [\"C1\", \"C2\"], " + "\"rowKeys\": [\"R1\", \"R2\"], " + "\"series\": [{\"seriesKey\": \"S1\", " + "\"rows\": [[\"R1\", [1.0, 2.0]], [\"R2\", [null, 3.0]]]}]}", dataset.toString()); dataset.addValue(4.0, "S2", "R2", "C2"); assertEquals("{\"columnKeys\": [\"C1\", \"C2\"], " + "\"rowKeys\": [\"R1\", \"R2\"], " + "\"series\": [{\"seriesKey\": \"S1\", " + "\"rows\": [[\"R1\", [1.0, 2.0]], [\"R2\", [null, 3.0]]]}, " + "{\"seriesKey\": \"S2\", \"rows\": [[\"R2\", [null, 4.0]]]}]}", dataset.toString()); } } orson-charts-2.1.0/src/test/java/org/jfree/chart3d/data/xyz/000077500000000000000000000000001417331271500236045ustar00rootroot00000000000000orson-charts-2.1.0/src/test/java/org/jfree/chart3d/data/xyz/XYZDataItemTest.java000066400000000000000000000051561417331271500274210ustar00rootroot00000000000000/* =========================================================== * Orson Charts : a 3D chart library for the Java(tm) platform * =========================================================== * * (C)opyright 2013-2022, by David Gilbert. All rights reserved. * * https://github.com/jfree/orson-charts * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . * * [Oracle and Java are registered trademarks of Oracle and/or its affiliates. * Other names may be trademarks of their respective owners.] * * If you do not wish to be bound by the terms of the GPL, an alternative * commercial license can be purchased. For details, please see visit the * Orson Charts home page: * * http://www.object-refinery.com/orsoncharts/index.html * */ package org.jfree.chart3d.data.xyz; import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertFalse; import static org.junit.jupiter.api.Assertions.assertTrue; import org.junit.jupiter.api.Test; import org.jfree.chart3d.TestUtils; /** * Tests for the {@link XYZDataItem} class. */ public class XYZDataItemTest { @Test public void testEquals() { XYZDataItem d1 = new XYZDataItem(1.0, 2.0, 3.0); XYZDataItem d2 = new XYZDataItem(1.0, 2.0, 3.0); assertTrue(d1.equals(d2)); assertFalse(d1.equals(null)); d1 = new XYZDataItem(1.1, 2.0, 3.0); assertFalse(d1.equals(d2)); d2 = new XYZDataItem(1.1, 2.0, 3.0); assertTrue(d1.equals(d2)); d1 = new XYZDataItem(1.1, 2.2, 3.0); assertFalse(d1.equals(d2)); d2 = new XYZDataItem(1.1, 2.2, 3.0); assertTrue(d1.equals(d2)); d1 = new XYZDataItem(1.1, 2.2, 3.3); assertFalse(d1.equals(d2)); d2 = new XYZDataItem(1.1, 2.2, 3.3); assertTrue(d1.equals(d2)); } @Test public void testSerialization() { XYZDataItem d1 = new XYZDataItem(1.0, 2.0, 3.0); XYZDataItem d2 = (XYZDataItem) TestUtils.serialized(d1); assertEquals(d1, d2); } } orson-charts-2.1.0/src/test/java/org/jfree/chart3d/data/xyz/XYZItemKeyTest.java000066400000000000000000000050541417331271500272750ustar00rootroot00000000000000/* =========================================================== * Orson Charts : a 3D chart library for the Java(tm) platform * =========================================================== * * (C)opyright 2013-2022, by David Gilbert. All rights reserved. * * https://github.com/jfree/orson-charts * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . * * [Oracle and Java are registered trademarks of Oracle and/or its affiliates. * Other names may be trademarks of their respective owners.] * * If you do not wish to be bound by the terms of the GPL, an alternative * commercial license can be purchased. For details, please see visit the * Orson Charts home page: * * http://www.object-refinery.com/orsoncharts/index.html * */ package org.jfree.chart3d.data.xyz; import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertFalse; import static org.junit.jupiter.api.Assertions.assertTrue; import org.junit.jupiter.api.Test; import org.jfree.chart3d.TestUtils; /** * Tests for the {@link XYZItemKey} class. */ public class XYZItemKeyTest { @Test public void testEquals() { XYZItemKey k1 = new XYZItemKey<>("S1", 1); XYZItemKey k2 = new XYZItemKey<>("S1", 1); assertTrue(k1.equals(k2)); assertFalse(k1.equals(null)); k1 = new XYZItemKey<>("S2", 1); assertFalse(k1.equals(k2)); k2 = new XYZItemKey<>("S2", 1); assertTrue(k1.equals(k2)); k1 = new XYZItemKey<>("S2", 2); assertFalse(k1.equals(k2)); k2 = new XYZItemKey<>("S2", 2); assertTrue(k1.equals(k2)); } /** * Check for serialization support. */ @Test @SuppressWarnings("unchecked") public void testSerialization() { XYZItemKey k1 = new XYZItemKey<>("S1", 1); XYZItemKey k2 = (XYZItemKey) TestUtils.serialized(k1); assertEquals(k1, k2); } } orson-charts-2.1.0/src/test/java/org/jfree/chart3d/data/xyz/XYZSeriesCollectionTest.java000066400000000000000000000127771417331271500312060ustar00rootroot00000000000000/* =========================================================== * Orson Charts : a 3D chart library for the Java(tm) platform * =========================================================== * * (C)opyright 2013-2022, by David Gilbert. All rights reserved. * * https://github.com/jfree/orson-charts * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . * * [Oracle and Java are registered trademarks of Oracle and/or its affiliates. * Other names may be trademarks of their respective owners.] * * If you do not wish to be bound by the terms of the GPL, an alternative * commercial license can be purchased. For details, please see visit the * Orson Charts home page: * * http://www.object-refinery.com/orsoncharts/index.html * */ package org.jfree.chart3d.data.xyz; import static org.junit.jupiter.api.Assertions.assertNull; import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertFalse; import static org.junit.jupiter.api.Assertions.assertNotNull; import static org.junit.jupiter.api.Assertions.assertTrue; import static org.junit.jupiter.api.Assertions.fail; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.BeforeEach; import org.jfree.chart3d.TestUtils; import org.jfree.chart3d.data.Dataset3DChangeEvent; import org.jfree.chart3d.data.Dataset3DChangeListener; /** * Tests for the {@link XYZSeriesCollection} class. */ public class XYZSeriesCollectionTest implements Dataset3DChangeListener { private Dataset3DChangeEvent lastEvent; @BeforeEach public void setup() { this.lastEvent = null; } @Override public void datasetChanged(Dataset3DChangeEvent event) { this.lastEvent = event; } @Test public void testGeneral() { XYZSeriesCollection dataset = new XYZSeriesCollection<>(); assertTrue(dataset.isNotify()); } @Test public void testAdd() { XYZSeriesCollection dataset = new XYZSeriesCollection<>(); XYZSeries s = new XYZSeries<>("S1"); dataset.add(s); assertEquals(1, dataset.getSeriesCount()); try { dataset.add(new XYZSeries<>("S1")); fail("Adding a series with the same name not permitted."); } catch (IllegalArgumentException e) { // expected } } /** * Modifying a dataset should trigger a dataset change event. */ @Test public void testEventNotification() { XYZSeriesCollection dataset = new XYZSeriesCollection<>(); dataset.addChangeListener(this); assertNull(this.lastEvent); XYZSeries s = new XYZSeries<>("S1"); dataset.add(s); assertNotNull(this.lastEvent); this.lastEvent = null; s.add(1.0, 2.0, 3.0); assertNotNull(this.lastEvent); this.lastEvent = null; s.add(new XYZDataItem(1.0, 2.0, 3.0)); assertNotNull(this.lastEvent); this.lastEvent = null; s.remove(1); assertNotNull(this.lastEvent); } @Test public void testEquals() { XYZSeriesCollection c1 = new XYZSeriesCollection<>(); XYZSeriesCollection c2 = new XYZSeriesCollection<>(); assertTrue(c1.equals(c2)); assertFalse(c1.equals(null)); XYZSeries s1 = new XYZSeries<>("S"); s1.add(1.0, 2.0, 3.0); c1.add(s1); assertFalse(c1.equals(c2)); XYZSeries s2 = new XYZSeries<>("S"); s2.add(1.0, 2.0, 3.0); c2.add(s2); assertEquals(c1, c2); } @Test @SuppressWarnings("unchecked") public void testSerialization() { XYZSeries s1 = new XYZSeries<>("S"); s1.add(1.0, 2.0, 3.0); XYZSeriesCollection c1 = new XYZSeriesCollection<>(); c1.add(s1); XYZSeriesCollection c2 = (XYZSeriesCollection) TestUtils.serialized(c1); assertEquals(c1, c2); } @Test public void checkToString() { XYZSeriesCollection c = new XYZSeriesCollection<>(); assertEquals("[]", c.toString()); XYZSeries s1 = new XYZSeries<>("S1"); c.add(s1); assertEquals("[[\"S1\", []]]", c.toString()); s1.add(1.0, 2.0, 3.0); assertEquals("[[\"S1\", [[1.0, 2.0, 3.0]]]]", c.toString()); s1.add(4.0, 5.0, 6.0); assertEquals("[[\"S1\", [[1.0, 2.0, 3.0], [4.0, 5.0, 6.0]]]]", c.toString()); XYZSeries s2 = new XYZSeries<>("S2"); c.add(s2); assertEquals("[[\"S1\", [[1.0, 2.0, 3.0], [4.0, 5.0, 6.0]]], " + "[\"S2\", []]]", c.toString()); s2.add(7.0, Double.NaN, 9.0); assertEquals("[[\"S1\", [[1.0, 2.0, 3.0], [4.0, 5.0, 6.0]]], " + "[\"S2\", [[7.0, null, 9.0]]]]", c.toString()); } } orson-charts-2.1.0/src/test/java/org/jfree/chart3d/data/xyz/XYZSeriesTest.java000066400000000000000000000104741417331271500271620ustar00rootroot00000000000000/* =========================================================== * Orson Charts : a 3D chart library for the Java(tm) platform * =========================================================== * * (C)opyright 2013-2022, by David Gilbert. All rights reserved. * * https://github.com/jfree/orson-charts * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . * * [Oracle and Java are registered trademarks of Oracle and/or its affiliates. * Other names may be trademarks of their respective owners.] * * If you do not wish to be bound by the terms of the GPL, an alternative * commercial license can be purchased. For details, please see visit the * Orson Charts home page: * * http://www.object-refinery.com/orsoncharts/index.html * */ package org.jfree.chart3d.data.xyz; import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertFalse; import static org.junit.jupiter.api.Assertions.assertTrue; import static org.junit.jupiter.api.Assertions.assertNotNull; import org.junit.jupiter.api.Test; import org.jfree.chart3d.TestUtils; import org.jfree.chart3d.data.Series3DChangeEvent; import org.jfree.chart3d.data.Series3DChangeListener; /** * Tests for the {@link XYZSeries} class. */ public class XYZSeriesTest implements Series3DChangeListener { private static final double EPSILON = 0.00000001; private Series3DChangeEvent lastEvent; @Test public void testGeneral() { XYZSeries s = new XYZSeries<>("S1"); assertEquals("S1", s.getKey()); assertEquals(0, s.getItemCount()); s.add(1.0, 2.0, 3.0); assertEquals(1, s.getItemCount()); assertEquals(1.0, s.getXValue(0), EPSILON); assertEquals(2.0, s.getYValue(0), EPSILON); assertEquals(3.0, s.getZValue(0), EPSILON); s.add(4.0, 5.0, 6.0); assertEquals(2, s.getItemCount()); assertEquals(4.0, s.getXValue(1), EPSILON); assertEquals(5.0, s.getYValue(1), EPSILON); assertEquals(6.0, s.getZValue(1), EPSILON); s.remove(0); assertEquals(1, s.getItemCount()); assertEquals(4.0, s.getXValue(0), EPSILON); assertEquals(5.0, s.getYValue(0), EPSILON); assertEquals(6.0, s.getZValue(0), EPSILON); } @Test public void testEventNotification() { XYZSeries s = new XYZSeries<>("S1"); this.lastEvent = null; s.addChangeListener(this); s.add(1.0, 2.0, 3.0); assertNotNull(this.lastEvent); this.lastEvent = null; s.remove(0); assertNotNull(this.lastEvent); } /** * Tests for the equals() method. */ @Test public void testEquals() { XYZSeries s1 = new XYZSeries<>("S"); XYZSeries s2 = new XYZSeries<>("S"); assertTrue(s1.equals(s2)); assertFalse(s1.equals(null)); // key s1 = new XYZSeries<>("SS"); assertFalse(s1.equals(s2)); s2 = new XYZSeries<>("SS"); assertTrue(s1.equals(s2)); // data items s1.add(1.0, 2.0, 3.0); assertFalse(s1.equals(s2)); s2.add(1.0, 2.0, 3.0); assertTrue(s1.equals(s2)); } /** * Checks for serialization support. */ @Test @SuppressWarnings("unchecked") public void testSerialization() { XYZSeries s1 = new XYZSeries<>("S"); XYZSeries s2 = (XYZSeries) TestUtils.serialized(s1); assertEquals(s1, s2); s1.add(1.0, 2.0, 3.0); s2 = (XYZSeries) TestUtils.serialized(s1); assertEquals(s1, s2); } @Override public void seriesChanged(Series3DChangeEvent event) { this.lastEvent = event; } } orson-charts-2.1.0/src/test/java/org/jfree/chart3d/graphics2d/000077500000000000000000000000001417331271500240675ustar00rootroot00000000000000orson-charts-2.1.0/src/test/java/org/jfree/chart3d/graphics2d/Anchor2DTest.java000066400000000000000000000062311417331271500271740ustar00rootroot00000000000000/* =========================================================== * Orson Charts : a 3D chart library for the Java(tm) platform * =========================================================== * * (C)opyright 2013-2022, by David Gilbert. All rights reserved. * * https://github.com/jfree/orson-charts * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . * * [Oracle and Java are registered trademarks of Oracle and/or its affiliates. * Other names may be trademarks of their respective owners.] * * If you do not wish to be bound by the terms of the GPL, an alternative * commercial license can be purchased. For details, please see visit the * Orson Charts home page: * * http://www.object-refinery.com/orsoncharts/index.html * */ package org.jfree.chart3d.graphics2d; import org.jfree.chart3d.TestUtils; import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertTrue; import static org.junit.jupiter.api.Assertions.assertFalse; import java.awt.Rectangle; import java.awt.geom.Point2D; import org.jfree.chart3d.graphics3d.Offset2D; import org.junit.jupiter.api.Test; /** * Some checks for the {@link Anchor2D} class. */ public class Anchor2DTest { private static final double EPSILON = 0.00000001; @Test public void testGeneral() { Anchor2D anchor = new Anchor2D(RefPt2D.BOTTOM_LEFT, new Offset2D(5.0, 10.0)); Point2D pt = anchor.getAnchorPoint(new Rectangle(10, 20, 30, 40)); assertEquals(new Point2D.Double(15, 50), pt); } /** * Checks for the equals() method. */ @Test public void testEquals() { Anchor2D a1 = new Anchor2D(RefPt2D.BOTTOM_CENTER, new Offset2D(1.0, 2.0)); Anchor2D a2 = new Anchor2D(RefPt2D.BOTTOM_CENTER, new Offset2D(1.0, 2.0)); assertTrue(a1.equals(a2)); assertFalse(a1.equals(null)); a1 = new Anchor2D(RefPt2D.CENTER, new Offset2D(1.0, 2.0)); assertFalse(a1.equals(a2)); a2 = new Anchor2D(RefPt2D.CENTER, new Offset2D(1.0, 2.0)); assertTrue(a1.equals(a2)); a1 = new Anchor2D(RefPt2D.CENTER, new Offset2D(3.0, 2.0)); assertFalse(a1.equals(a2)); a2 = new Anchor2D(RefPt2D.CENTER, new Offset2D(3.0, 2.0)); assertTrue(a1.equals(a2)); } @Test public void testSerialization() { Anchor2D a1 = new Anchor2D(RefPt2D.BOTTOM_CENTER, new Offset2D(1.0, 2.0)); Anchor2D a2 = (Anchor2D) TestUtils.serialized(a1); assertEquals(a1, a2); } } orson-charts-2.1.0/src/test/java/org/jfree/chart3d/graphics2d/Fit2DTest.java000066400000000000000000000064561417331271500265150ustar00rootroot00000000000000/* =========================================================== * Orson Charts : a 3D chart library for the Java(tm) platform * =========================================================== * * (C)opyright 2013-2022, by David Gilbert. All rights reserved. * * https://github.com/jfree/orson-charts * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . * * [Oracle and Java are registered trademarks of Oracle and/or its affiliates. * Other names may be trademarks of their respective owners.] * * If you do not wish to be bound by the terms of the GPL, an alternative * commercial license can be purchased. For details, please see visit the * Orson Charts home page: * * http://www.object-refinery.com/orsoncharts/index.html * */ package org.jfree.chart3d.graphics2d; import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertFalse; import static org.junit.jupiter.api.Assertions.assertTrue; import org.junit.jupiter.api.Test; import java.awt.Dimension; import java.awt.Rectangle; import java.awt.geom.Rectangle2D; import org.jfree.chart3d.TestUtils; import org.jfree.chart3d.TitleAnchor; /** * Tests for the {@link Fit2D} class. */ public class Fit2DTest { private static final double EPSILON = 0.00000001; @Test public void testEquals() { Fit2D f1 = new Fit2D(TitleAnchor.TOP_LEFT, Scale2D.SCALE_BOTH); Fit2D f2 = new Fit2D(TitleAnchor.TOP_LEFT, Scale2D.SCALE_BOTH); assertTrue(f1.equals(f2)); f1 = new Fit2D(TitleAnchor.CENTER_LEFT, Scale2D.SCALE_BOTH); assertFalse(f1.equals(f2)); f2 = new Fit2D(TitleAnchor.CENTER_LEFT, Scale2D.SCALE_BOTH); assertTrue(f1.equals(f2)); f1 = new Fit2D(TitleAnchor.CENTER_LEFT, Scale2D.NONE); assertFalse(f1.equals(f2)); f2 = new Fit2D(TitleAnchor.CENTER_LEFT, Scale2D.NONE); assertTrue(f1.equals(f2)); } /** * For SCALE_BOTH the result will always fill the target - the anchor is * not important. */ @Test public void testFit_ScaleBoth() { Fit2D f = new Fit2D(TitleAnchor.TOP_LEFT, Scale2D.SCALE_BOTH); Rectangle2D rect = f.fit(new Dimension(4, 5), new Rectangle(10, 10, 30, 20)); assertEquals(10, rect.getX(), EPSILON); assertEquals(10, rect.getY(), EPSILON); assertEquals(30, rect.getWidth(), EPSILON); assertEquals(20, rect.getHeight(), EPSILON); } /** * A check for serialization. */ @Test public void testSerialization() { Fit2D f1 = new Fit2D(TitleAnchor.BOTTOM_CENTER, Scale2D.SCALE_BOTH); Fit2D f2 = (Fit2D) TestUtils.serialized(f1); assertEquals(f1, f2); } } orson-charts-2.1.0/src/test/java/org/jfree/chart3d/graphics2d/Offset2DTest.java000066400000000000000000000047401417331271500272130ustar00rootroot00000000000000/* =========================================================== * Orson Charts : a 3D chart library for the Java(tm) platform * =========================================================== * * (C)opyright 2013-2022, by David Gilbert. All rights reserved. * * https://github.com/jfree/orson-charts * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . * * [Oracle and Java are registered trademarks of Oracle and/or its affiliates. * Other names may be trademarks of their respective owners.] * * If you do not wish to be bound by the terms of the GPL, an alternative * commercial license can be purchased. For details, please see visit the * Orson Charts home page: * * http://www.object-refinery.com/orsoncharts/index.html * */ package org.jfree.chart3d.graphics2d; import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertTrue; import static org.junit.jupiter.api.Assertions.assertFalse; import org.junit.jupiter.api.Test; import org.jfree.chart3d.TestUtils; import org.jfree.chart3d.graphics3d.Offset2D; /** * Some checks for the {@link Offset2D} class. */ public class Offset2DTest { @Test public void testEquals() { Offset2D off1 = new Offset2D(1.0, 2.0); Offset2D off2 = new Offset2D(1.0, 2.0); assertTrue(off1.equals(off2)); assertFalse(off1.equals(null)); off1 = new Offset2D(3.0, 2.0); assertFalse(off1.equals(off2)); off2 = new Offset2D(3.0, 2.0); assertTrue(off1.equals(off2)); off1 = new Offset2D(3.0, 4.0); assertFalse(off1.equals(off2)); off2 = new Offset2D(3.0, 4.0); assertTrue(off1.equals(off2)); } @Test public void testSerialization() { Offset2D off1 = new Offset2D(1.0, 2.0); Offset2D off2 = (Offset2D) TestUtils.serialized(off1); assertEquals(off1, off2); } } orson-charts-2.1.0/src/test/java/org/jfree/chart3d/graphics3d/000077500000000000000000000000001417331271500240705ustar00rootroot00000000000000orson-charts-2.1.0/src/test/java/org/jfree/chart3d/graphics3d/Dimension3DTest.java000066400000000000000000000050511417331271500277100ustar00rootroot00000000000000/* =========================================================== * Orson Charts : a 3D chart library for the Java(tm) platform * =========================================================== * * (C)opyright 2013-2022, by David Gilbert. All rights reserved. * * https://github.com/jfree/orson-charts * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . * * [Oracle and Java are registered trademarks of Oracle and/or its affiliates. * Other names may be trademarks of their respective owners.] * * If you do not wish to be bound by the terms of the GPL, an alternative * commercial license can be purchased. For details, please see visit the * Orson Charts home page: * * http://www.object-refinery.com/orsoncharts/index.html * */ package org.jfree.chart3d.graphics3d; import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertNotEquals; import org.junit.jupiter.api.Test; import org.jfree.chart3d.TestUtils; /** * Tests for the {@link Dimension3D} class. */ public class Dimension3DTest { @Test public void checkEquals() { Dimension3D dim1 = new Dimension3D(1, 2, 3); Dimension3D dim2 = new Dimension3D(1, 2, 3); assertEquals(dim1, dim2); dim1 = new Dimension3D(2, 2, 3); assertNotEquals(dim1, dim2); dim2 = new Dimension3D(2, 2, 3); assertEquals(dim1, dim2); dim1 = new Dimension3D(2, 1, 3); assertNotEquals(dim1, dim2); dim2 = new Dimension3D(2, 1, 3); assertEquals(dim1, dim2); dim1 = new Dimension3D(2, 1, 4); assertNotEquals(dim1, dim2); dim2 = new Dimension3D(2, 1, 4); assertEquals(dim1, dim2); } /** * A check for serialization. */ @Test public void testSerialization() { Dimension3D dim1 = new Dimension3D(1, 2, 3); Dimension3D dim2 = (Dimension3D) TestUtils.serialized(dim1); assertEquals(dim1, dim2); } } orson-charts-2.1.0/src/test/java/org/jfree/chart3d/graphics3d/Point3DTest.java000066400000000000000000000050751417331271500270620ustar00rootroot00000000000000/* =========================================================== * Orson Charts : a 3D chart library for the Java(tm) platform * =========================================================== * * (C)opyright 2013-2022, by David Gilbert. All rights reserved. * * https://github.com/jfree/orson-charts * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . * * [Oracle and Java are registered trademarks of Oracle and/or its affiliates. * Other names may be trademarks of their respective owners.] * * If you do not wish to be bound by the terms of the GPL, an alternative * commercial license can be purchased. For details, please see visit the * Orson Charts home page: * * http://www.object-refinery.com/orsoncharts/index.html * */ package org.jfree.chart3d.graphics3d; import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertFalse; import static org.junit.jupiter.api.Assertions.assertTrue; import org.junit.jupiter.api.Test; import org.jfree.chart3d.TestUtils; /** * Tests for the {link Point3D} class. */ public class Point3DTest { @Test public void testEquals() { Point3D p1 = new Point3D(1.0, 0.0, 0.0); Point3D p2 = new Point3D(1.0, 0.0, 0.0); assertTrue(p1.equals(p2)); p1 = new Point3D(1.1, 0.0, 0.0); assertFalse(p1.equals(p2)); p2 = new Point3D(1.1, 0.0, 0.0); assertTrue(p1.equals(p2)); p1 = new Point3D(1.1, 2.2, 0.0); assertFalse(p1.equals(p2)); p2 = new Point3D(1.1, 2.2, 0.0); assertTrue(p1.equals(p2)); p1 = new Point3D(1.1, 2.2, 3.3); assertFalse(p1.equals(p2)); p2 = new Point3D(1.1, 2.2, 3.3); assertTrue(p1.equals(p2)); } /** * A check for serialization. */ @Test public void testSerialization() { Point3D p1 = new Point3D(1.0, 2.0, 3.0); Point3D p2 = (Point3D) TestUtils.serialized(p1); assertEquals(p1, p2); } } orson-charts-2.1.0/src/test/java/org/jfree/chart3d/graphics3d/Rotate3DTest.java000066400000000000000000000042621417331271500272240ustar00rootroot00000000000000/* =========================================================== * Orson Charts : a 3D chart library for the Java(tm) platform * =========================================================== * * (C)opyright 2013-2022, by David Gilbert. All rights reserved. * * https://github.com/jfree/orson-charts * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . * * [Oracle and Java are registered trademarks of Oracle and/or its affiliates. * Other names may be trademarks of their respective owners.] * * If you do not wish to be bound by the terms of the GPL, an alternative * commercial license can be purchased. For details, please see visit the * Orson Charts home page: * * http://www.object-refinery.com/orsoncharts/index.html * */ package org.jfree.chart3d.graphics3d; import static org.junit.jupiter.api.Assertions.assertEquals; import org.junit.jupiter.api.Test; /** * * @author dgilbert */ public class Rotate3DTest { private static final double EPSILON = 0.0000001; @Test public void testGeneral() { Rotate3D r = new Rotate3D(Point3D.ORIGIN, Point3D.UNIT_X, Math.PI); Point3D p = r.applyRotation(1, 1, 1); assertEquals(1, p.x, EPSILON); assertEquals(-1, p.y, EPSILON); assertEquals(-1, p.z, EPSILON); } @Test public void test2() { ViewPoint3D v1 = new ViewPoint3D(-1.675516f, -2.6179938f, 25.874374f, 0); Rotate3D r = new Rotate3D(Point3D.ORIGIN, v1.getHorizontalRotationAxis(), -Math.PI / 60); Point3D p = r.applyRotation(v1.getPoint()); ViewPoint3D v2 = new ViewPoint3D(p, 0); } } orson-charts-2.1.0/src/test/java/org/jfree/chart3d/graphics3d/ViewPoint3DTest.java000066400000000000000000000121741417331271500277130ustar00rootroot00000000000000/* =========================================================== * Orson Charts : a 3D chart library for the Java(tm) platform * =========================================================== * * (C)opyright 2013-2022, by David Gilbert. All rights reserved. * * https://github.com/jfree/orson-charts * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . * * [Oracle and Java are registered trademarks of Oracle and/or its affiliates. * Other names may be trademarks of their respective owners.] * * If you do not wish to be bound by the terms of the GPL, an alternative * commercial license can be purchased. For details, please see visit the * Orson Charts home page: * * http://www.object-refinery.com/orsoncharts/index.html * */ package org.jfree.chart3d.graphics3d; import org.jfree.chart3d.TestUtils; import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertFalse; import static org.junit.jupiter.api.Assertions.assertTrue; import org.junit.jupiter.api.Test; /** * Some tests for the {@link ViewPoint3D} class. */ public class ViewPoint3DTest { private static final double EPSILON = 0.000001; @Test public void testGeneral() { ViewPoint3D v1 = new ViewPoint3D(0, 0, 1, 0); assertEquals(0, v1.getX(), EPSILON); assertEquals(0, v1.getY(), EPSILON); assertEquals(1, v1.getZ(), EPSILON); assertEquals(0, v1.calcRollAngle(), EPSILON); v1 = new ViewPoint3D(Point3D.UNIT_X, 0.0); assertEquals(0, v1.getTheta(), EPSILON); assertEquals(Math.PI / 2, v1.getPhi(), EPSILON); assertEquals(1, v1.getRho(), EPSILON); assertEquals(0, v1.calcRollAngle(), EPSILON); v1 = new ViewPoint3D(Point3D.UNIT_Y, 0.0); assertEquals(Math.PI / 2, v1.getTheta(), EPSILON); assertEquals(Math.PI / 2, v1.getPhi(), EPSILON); assertEquals(1, v1.getRho(), EPSILON); assertEquals(0, v1.calcRollAngle(), EPSILON); v1 = new ViewPoint3D(Point3D.UNIT_Z, 0.0); assertEquals(0, v1.getTheta(), EPSILON); assertEquals(0, v1.getPhi(), EPSILON); assertEquals(1, v1.getRho(), EPSILON); assertEquals(0, v1.calcRollAngle(), EPSILON); v1 = new ViewPoint3D(1, 2, 3, 4); ViewPoint3D v2 = new ViewPoint3D(v1.getPoint(), v1.calcRollAngle()); assertEquals(v1.getTheta(), v2.getTheta(), EPSILON); assertEquals(v1.getPhi(), v2.getPhi(), EPSILON); assertEquals(v1.getRho(), v2.getRho(), EPSILON); } @Test public void testConstructor() { ViewPoint3D v1 = new ViewPoint3D(-1.675516f, -2.6179938f, 25.874374f, 0); ViewPoint3D v2 = new ViewPoint3D(v1.getPoint(), v1.calcRollAngle()); assertEquals(v1.getX(), v2.getX(), EPSILON); assertEquals(v1.getY(), v2.getY(), EPSILON); assertEquals(v1.getZ(), v2.getZ(), EPSILON); } @Test public void testEquals() { ViewPoint3D vp1 = new ViewPoint3D(1.0, 2.0, 3.0, 4.0); ViewPoint3D vp2 = new ViewPoint3D(1.0, 2.0, 3.0, 4.0); assertTrue(vp1.equals(vp2)); vp1 = new ViewPoint3D(1.1, 2.0, 3.0, 4.0); assertFalse(vp1.equals(vp2)); vp2 = new ViewPoint3D(1.1, 2.0, 3.0, 4.0); assertTrue(vp1.equals(vp2)); vp1 = new ViewPoint3D(1.1, 2.2, 3.0, 4.0); assertFalse(vp1.equals(vp2)); vp2 = new ViewPoint3D(1.1, 2.2, 3.0, 4.0); assertTrue(vp1.equals(vp2)); vp1 = new ViewPoint3D(1.1, 2.2, 3.3, 4.0); assertFalse(vp1.equals(vp2)); vp2 = new ViewPoint3D(1.1, 2.2, 3.3, 4.0); assertTrue(vp1.equals(vp2)); vp1 = new ViewPoint3D(1.1, 2.2, 3.3, 4.4); assertFalse(vp1.equals(vp2)); vp2 = new ViewPoint3D(1.1, 2.2, 3.3, 4.4); assertTrue(vp1.equals(vp2)); vp1.moveUpDown(1.0); assertFalse(vp1.equals(vp2)); vp2.moveUpDown(1.0); assertTrue(vp1.equals(vp2)); } /** * A check for serialization. */ @Test public void testSerialization() { ViewPoint3D vp1 = new ViewPoint3D(1.0, 2.0, 3.0, 4.0); ViewPoint3D vp2 = (ViewPoint3D) TestUtils.serialized(vp1); assertEquals(vp1, vp2); } @Test public void testZ() { Point3D p = new Point3D(0, 0, 25); ViewPoint3D v1 = new ViewPoint3D(p, 0); assertEquals(0, v1.getX(), EPSILON); assertEquals(0, v1.getY(), EPSILON); assertEquals(25, v1.getZ(), EPSILON); assertEquals(0, v1.getTheta(), EPSILON); } } orson-charts-2.1.0/src/test/java/org/jfree/chart3d/graphics3d/internal/000077500000000000000000000000001417331271500257045ustar00rootroot00000000000000orson-charts-2.1.0/src/test/java/org/jfree/chart3d/graphics3d/internal/Utils3DTest.java000066400000000000000000000041531417331271500307010ustar00rootroot00000000000000/* =========================================================== * Orson Charts : a 3D chart library for the Java(tm) platform * =========================================================== * * (C)opyright 2013-2022, by David Gilbert. All rights reserved. * * https://github.com/jfree/orson-charts * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . * * [Oracle and Java are registered trademarks of Oracle and/or its affiliates. * Other names may be trademarks of their respective owners.] * * If you do not wish to be bound by the terms of the GPL, an alternative * commercial license can be purchased. For details, please see visit the * Orson Charts home page: * * http://www.object-refinery.com/orsoncharts/index.html * */ package org.jfree.chart3d.graphics3d.internal; import org.jfree.chart3d.graphics3d.Point3D; import static org.junit.jupiter.api.Assertions.assertEquals; import org.junit.jupiter.api.Test; /** * Some tests for the methods in {@link Utils3D}. */ public class Utils3DTest { private static final double EPSILON = 0.00000001; @Test public void testLength() { assertEquals(1, Utils3D.length(Point3D.UNIT_X), EPSILON); assertEquals(1, Utils3D.length(Point3D.UNIT_Y), EPSILON); assertEquals(1, Utils3D.length(Point3D.UNIT_Z), EPSILON); assertEquals(0, Utils3D.length(Point3D.ORIGIN), EPSILON); } @Test public void testAngle() { assertEquals(Math.PI / 2, Utils3D.angle(Point3D.UNIT_X, Point3D.UNIT_Y), EPSILON); } } orson-charts-2.1.0/src/test/java/org/jfree/chart3d/interaction/000077500000000000000000000000001417331271500243605ustar00rootroot00000000000000StandardKeyedValues3DItemSelectionTest.java000066400000000000000000000047101417331271500345640ustar00rootroot00000000000000orson-charts-2.1.0/src/test/java/org/jfree/chart3d/interaction/* =========================================================== * Orson Charts : a 3D chart library for the Java(tm) platform * =========================================================== * * (C)opyright 2013-2022, by David Gilbert. All rights reserved. * * https://github.com/jfree/orson-charts * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . * * [Oracle and Java are registered trademarks of Oracle and/or its affiliates. * Other names may be trademarks of their respective owners.] * * If you do not wish to be bound by the terms of the GPL, an alternative * commercial license can be purchased. For details, please see visit the * Orson Charts home page: * * http://www.object-refinery.com/orsoncharts/index.html * */ package org.jfree.chart3d.interaction; import static org.junit.jupiter.api.Assertions.assertFalse; import static org.junit.jupiter.api.Assertions.assertTrue; import org.junit.jupiter.api.Test; import org.jfree.chart3d.TestUtils; /** * Tests for the {@link StandardKeyedValues3DItemSelection} class. */ public class StandardKeyedValues3DItemSelectionTest { /** * Some checks for the equals() method. */ @Test public void testEquals() { StandardKeyedValues3DItemSelection s1 = new StandardKeyedValues3DItemSelection(); StandardKeyedValues3DItemSelection s2 = new StandardKeyedValues3DItemSelection(); assertTrue(s1.equals(s2)); assertFalse(s1.equals(null)); } /** * Checks for serialization support. */ @Test public void testSerialization() { StandardKeyedValues3DItemSelection s1 = new StandardKeyedValues3DItemSelection(); StandardKeyedValues3DItemSelection s2 = (StandardKeyedValues3DItemSelection) TestUtils.serialized(s1); assertTrue(s1.equals(s2)); } } orson-charts-2.1.0/src/test/java/org/jfree/chart3d/label/000077500000000000000000000000001417331271500231205ustar00rootroot00000000000000orson-charts-2.1.0/src/test/java/org/jfree/chart3d/label/StandardCategoryItemLabelGeneratorTest.java000066400000000000000000000052161417331271500335130ustar00rootroot00000000000000/* =========================================================== * Orson Charts : a 3D chart library for the Java(tm) platform * =========================================================== * * (C)opyright 2013-2022, by David Gilbert. All rights reserved. * * https://github.com/jfree/orson-charts * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . * * [Oracle and Java are registered trademarks of Oracle and/or its affiliates. * Other names may be trademarks of their respective owners.] * * If you do not wish to be bound by the terms of the GPL, an alternative * commercial license can be purchased. For details, please see visit the * Orson Charts home page: * * http://www.object-refinery.com/orsoncharts/index.html * */ package org.jfree.chart3d.label; import static org.junit.jupiter.api.Assertions.assertFalse; import static org.junit.jupiter.api.Assertions.assertTrue; import org.junit.jupiter.api.Test; import org.jfree.chart3d.TestUtils; /** * Tests for the {@link StandardCategoryItemLabelGenerator} class. */ public class StandardCategoryItemLabelGeneratorTest { /** * Some checks for the equals() method. */ @Test public void testEquals() { StandardCategoryItemLabelGenerator g1 = new StandardCategoryItemLabelGenerator(); StandardCategoryItemLabelGenerator g2 = new StandardCategoryItemLabelGenerator(); assertTrue(g1.equals(g2)); assertFalse(g1.equals(null)); g1 = new StandardCategoryItemLabelGenerator("%s TEST"); assertFalse(g1.equals(g2)); g2 = new StandardCategoryItemLabelGenerator("%s TEST"); assertTrue(g1.equals(g2)); } /** * Checks for serialization support. */ @Test public void testSerialization() { StandardCategoryItemLabelGenerator g1 = new StandardCategoryItemLabelGenerator(); StandardCategoryItemLabelGenerator g2 = (StandardCategoryItemLabelGenerator) TestUtils.serialized(g1); assertTrue(g1.equals(g2)); } } orson-charts-2.1.0/src/test/java/org/jfree/chart3d/label/StandardCategoryLabelGeneratorTest.java000066400000000000000000000051561417331271500326770ustar00rootroot00000000000000/* =========================================================== * Orson Charts : a 3D chart library for the Java(tm) platform * =========================================================== * * (C)opyright 2013-2022, by David Gilbert. All rights reserved. * * https://github.com/jfree/orson-charts * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . * * [Oracle and Java are registered trademarks of Oracle and/or its affiliates. * Other names may be trademarks of their respective owners.] * * If you do not wish to be bound by the terms of the GPL, an alternative * commercial license can be purchased. For details, please see visit the * Orson Charts home page: * * http://www.object-refinery.com/orsoncharts/index.html * */ package org.jfree.chart3d.label; import static org.junit.jupiter.api.Assertions.assertFalse; import static org.junit.jupiter.api.Assertions.assertTrue; import org.junit.jupiter.api.Test; import org.jfree.chart3d.TestUtils; /** * Tests for the {@link StandardCategoryLabelGenerator} class. */ public class StandardCategoryLabelGeneratorTest { /** * Some checks for the equals() method. */ @Test public void testEquals() { StandardCategoryLabelGenerator lg1 = new StandardCategoryLabelGenerator(); StandardCategoryLabelGenerator lg2 = new StandardCategoryLabelGenerator(); assertTrue(lg1.equals(lg2)); assertFalse(lg1.equals(null)); lg1 = new StandardCategoryLabelGenerator("%s TEST"); assertFalse(lg1.equals(lg2)); lg2 = new StandardCategoryLabelGenerator("%s TEST"); assertTrue(lg1.equals(lg2)); } /** * Checks for serialization support. */ @Test public void testSerialization() { StandardCategoryLabelGenerator lg1 = new StandardCategoryLabelGenerator(); StandardCategoryLabelGenerator lg2 = (StandardCategoryLabelGenerator) TestUtils.serialized(lg1); assertTrue(lg1.equals(lg2)); } } orson-charts-2.1.0/src/test/java/org/jfree/chart3d/label/StandardPieLabelGeneratorTest.java000066400000000000000000000047601417331271500316370ustar00rootroot00000000000000/* =========================================================== * Orson Charts : a 3D chart library for the Java(tm) platform * =========================================================== * * (C)opyright 2013-2022, by David Gilbert. All rights reserved. * * https://github.com/jfree/orson-charts * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . * * [Oracle and Java are registered trademarks of Oracle and/or its affiliates. * Other names may be trademarks of their respective owners.] * * If you do not wish to be bound by the terms of the GPL, an alternative * commercial license can be purchased. For details, please see visit the * Orson Charts home page: * * http://www.object-refinery.com/orsoncharts/index.html * */ package org.jfree.chart3d.label; import static org.junit.jupiter.api.Assertions.assertFalse; import static org.junit.jupiter.api.Assertions.assertTrue; import org.junit.jupiter.api.Test; import org.jfree.chart3d.TestUtils; /** * Tests for the {@link StandardPieLabelGenerator} class. */ public class StandardPieLabelGeneratorTest { /** * Some checks for the equals() method. */ @Test public void testEquals() { StandardPieLabelGenerator lg1 = new StandardPieLabelGenerator(); StandardPieLabelGenerator lg2 = new StandardPieLabelGenerator(); assertTrue(lg1.equals(lg2)); assertFalse(lg1.equals(null)); lg1 = new StandardPieLabelGenerator("%s"); assertFalse(lg1.equals(lg2)); lg2 = new StandardPieLabelGenerator("%s"); assertTrue(lg1.equals(lg2)); } /** * Checks for serialization support. */ @Test public void testSerialization() { StandardPieLabelGenerator lg1 = new StandardPieLabelGenerator(); StandardPieLabelGenerator lg2 = new StandardPieLabelGenerator(); TestUtils.serialized(lg1); assertTrue(lg1.equals(lg2)); } } orson-charts-2.1.0/src/test/java/org/jfree/chart3d/label/StandardXYZLabelGeneratorTest.java000066400000000000000000000047721417331271500316170ustar00rootroot00000000000000/* =========================================================== * Orson Charts : a 3D chart library for the Java(tm) platform * =========================================================== * * (C)opyright 2013-2022, by David Gilbert. All rights reserved. * * https://github.com/jfree/orson-charts * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . * * [Oracle and Java are registered trademarks of Oracle and/or its affiliates. * Other names may be trademarks of their respective owners.] * * If you do not wish to be bound by the terms of the GPL, an alternative * commercial license can be purchased. For details, please see visit the * Orson Charts home page: * * http://www.object-refinery.com/orsoncharts/index.html * */ package org.jfree.chart3d.label; import static org.junit.jupiter.api.Assertions.assertFalse; import static org.junit.jupiter.api.Assertions.assertTrue; import org.junit.jupiter.api.Test; import org.jfree.chart3d.TestUtils; /** * Tests for the {@link StandardXYZLabelGenerator} class. */ public class StandardXYZLabelGeneratorTest { /** * Some checks for the equals() method. */ @Test public void testEquals() { StandardXYZLabelGenerator lg1 = new StandardXYZLabelGenerator(); StandardXYZLabelGenerator lg2 = new StandardXYZLabelGenerator(); assertTrue(lg1.equals(lg2)); assertFalse(lg1.equals(null)); lg1 = new StandardXYZLabelGenerator("%s TEST"); assertFalse(lg1.equals(lg2)); lg2 = new StandardXYZLabelGenerator("%s TEST"); assertTrue(lg1.equals(lg2)); } /** * Checks for serialization support. */ @Test public void testSerialization() { StandardXYZLabelGenerator lg1 = new StandardXYZLabelGenerator(); StandardXYZLabelGenerator lg2 = new StandardXYZLabelGenerator(); TestUtils.serialized(lg1); assertTrue(lg1.equals(lg2)); } } orson-charts-2.1.0/src/test/java/org/jfree/chart3d/legend/000077500000000000000000000000001417331271500232775ustar00rootroot00000000000000orson-charts-2.1.0/src/test/java/org/jfree/chart3d/legend/ColorScaleElementTest.java000066400000000000000000000116001417331271500303400ustar00rootroot00000000000000/* =========================================================== * Orson Charts : a 3D chart library for the Java(tm) platform * =========================================================== * * (C)opyright 2013-2022, by David Gilbert. All rights reserved. * * https://github.com/jfree/orson-charts * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . * * [Oracle and Java are registered trademarks of Oracle and/or its affiliates. * Other names may be trademarks of their respective owners.] * * If you do not wish to be bound by the terms of the GPL, an alternative * commercial license can be purchased. For details, please see visit the * Orson Charts home page: * * http://www.object-refinery.com/orsoncharts/index.html * */ package org.jfree.chart3d.legend; import static org.junit.jupiter.api.Assertions.assertFalse; import static org.junit.jupiter.api.Assertions.assertTrue; import java.awt.Color; import java.awt.Font; import org.jfree.chart3d.Orientation; import org.junit.jupiter.api.Test; import org.jfree.chart3d.TestUtils; import org.jfree.chart3d.renderer.FixedColorScale; /** * Tests for the {@link ColorScaleElement} class. */ public class ColorScaleElementTest { @Test public void testEquals() { ColorScaleElement cs1 = new ColorScaleElement( new FixedColorScale(Color.BLUE), Orientation.HORIZONTAL, 1.0, 2.0, new Font(Font.SERIF, Font.PLAIN, 10), Color.BLACK); ColorScaleElement cs2 = new ColorScaleElement( new FixedColorScale(Color.BLUE), Orientation.HORIZONTAL, 1.0, 2.0, new Font(Font.SERIF, Font.PLAIN, 10), Color.BLACK); assertTrue(cs1.equals(cs2)); assertFalse(cs1.equals(null)); cs1 = new ColorScaleElement( new FixedColorScale(Color.RED), Orientation.HORIZONTAL, 1.0, 2.0, new Font(Font.SERIF, Font.PLAIN, 10), Color.BLACK); assertFalse(cs1.equals(cs2)); cs2 = new ColorScaleElement( new FixedColorScale(Color.RED), Orientation.HORIZONTAL, 1.0, 2.0, new Font(Font.SERIF, Font.PLAIN, 10), Color.BLACK); assertTrue(cs1.equals(cs2)); cs1 = new ColorScaleElement( new FixedColorScale(Color.RED), Orientation.VERTICAL, 1.0, 2.0, new Font(Font.SERIF, Font.PLAIN, 10), Color.BLACK); assertFalse(cs1.equals(cs2)); cs2 = new ColorScaleElement( new FixedColorScale(Color.RED), Orientation.VERTICAL, 1.0, 2.0, new Font(Font.SERIF, Font.PLAIN, 10), Color.BLACK); assertTrue(cs1.equals(cs2)); cs1 = new ColorScaleElement( new FixedColorScale(Color.RED), Orientation.VERTICAL, 1.1, 2.0, new Font(Font.SERIF, Font.PLAIN, 10), Color.BLACK); assertFalse(cs1.equals(cs2)); cs2 = new ColorScaleElement( new FixedColorScale(Color.RED), Orientation.VERTICAL, 1.1, 2.0, new Font(Font.SERIF, Font.PLAIN, 10), Color.BLACK); assertTrue(cs1.equals(cs2)); cs1 = new ColorScaleElement( new FixedColorScale(Color.RED), Orientation.VERTICAL, 1.1, 2.2, new Font(Font.SERIF, Font.PLAIN, 10), Color.BLACK); assertFalse(cs1.equals(cs2)); cs2 = new ColorScaleElement( new FixedColorScale(Color.RED), Orientation.VERTICAL, 1.1, 2.2, new Font(Font.SERIF, Font.PLAIN, 10), Color.BLACK); assertTrue(cs1.equals(cs2)); cs1 = new ColorScaleElement( new FixedColorScale(Color.RED), Orientation.VERTICAL, 1.1, 2.2, new Font(Font.SERIF, Font.PLAIN, 22), Color.BLACK); assertFalse(cs1.equals(cs2)); cs2 = new ColorScaleElement( new FixedColorScale(Color.RED), Orientation.VERTICAL, 1.1, 2.2, new Font(Font.SERIF, Font.PLAIN, 22), Color.BLACK); assertTrue(cs1.equals(cs2)); } @Test public void testSerialization() { ColorScaleElement cs1 = new ColorScaleElement( new FixedColorScale(Color.BLUE), Orientation.HORIZONTAL, 1.0, 2.0, new Font(Font.SERIF, Font.PLAIN, 10), Color.BLACK); ColorScaleElement cs2 = (ColorScaleElement) TestUtils.serialized(cs1); assertTrue(cs1.equals(cs2)); } } orson-charts-2.1.0/src/test/java/org/jfree/chart3d/legend/ColorScaleLegendBuilderTest.java000066400000000000000000000051131417331271500314560ustar00rootroot00000000000000/* =========================================================== * Orson Charts : a 3D chart library for the Java(tm) platform * =========================================================== * * (C)opyright 2013-2022, by David Gilbert. All rights reserved. * * https://github.com/jfree/orson-charts * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . * * [Oracle and Java are registered trademarks of Oracle and/or its affiliates. * Other names may be trademarks of their respective owners.] * * If you do not wish to be bound by the terms of the GPL, an alternative * commercial license can be purchased. For details, please see visit the * Orson Charts home page: * * http://www.object-refinery.com/orsoncharts/index.html * */ package org.jfree.chart3d.legend; import static org.junit.jupiter.api.Assertions.assertFalse; import static org.junit.jupiter.api.Assertions.assertTrue; import org.junit.jupiter.api.Test; import org.jfree.chart3d.TestUtils; /** * Tests for the {@link ColorScaleLegendBuilder} class. */ public class ColorScaleLegendBuilderTest { /** * Some checks for the equals() method. */ @Test public void testEquals() { ColorScaleLegendBuilder lb1 = new ColorScaleLegendBuilder(); ColorScaleLegendBuilder lb2 = new ColorScaleLegendBuilder(); assertTrue(lb1.equals(lb2)); assertFalse(lb1.equals(null)); lb1.setBarWidth(123); assertFalse(lb1.equals(lb2)); lb2.setBarWidth(123); assertTrue(lb1.equals(lb2)); lb1.setBarLength(321); assertFalse(lb1.equals(lb2)); lb2.setBarLength(321); assertTrue(lb1.equals(lb2)); } /** * Checks for serialization support. */ @Test public void testSerialization() { ColorScaleLegendBuilder lb1 = new ColorScaleLegendBuilder(); ColorScaleLegendBuilder lb2 = (ColorScaleLegendBuilder) TestUtils.serialized(lb1); assertTrue(lb1.equals(lb2)); } } orson-charts-2.1.0/src/test/java/org/jfree/chart3d/legend/StandardLegendBuilderTest.java000066400000000000000000000056461417331271500312030ustar00rootroot00000000000000/* =========================================================== * Orson Charts : a 3D chart library for the Java(tm) platform * =========================================================== * * (C)opyright 2013-2022, by David Gilbert. All rights reserved. * * https://github.com/jfree/orson-charts * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . * * [Oracle and Java are registered trademarks of Oracle and/or its affiliates. * Other names may be trademarks of their respective owners.] * * If you do not wish to be bound by the terms of the GPL, an alternative * commercial license can be purchased. For details, please see visit the * Orson Charts home page: * * http://www.object-refinery.com/orsoncharts/index.html * */ package org.jfree.chart3d.legend; import static org.junit.jupiter.api.Assertions.assertFalse; import static org.junit.jupiter.api.Assertions.assertTrue; import org.junit.jupiter.api.Test; import org.jfree.chart3d.TestUtils; import org.jfree.chart3d.table.HAlign; /** * Tests for the {@link StandardLegendBuilder} class. */ public class StandardLegendBuilderTest { /** * Some checks for the equals() method. */ @Test public void testEquals() { StandardLegendBuilder lb1 = new StandardLegendBuilder(); StandardLegendBuilder lb2 = new StandardLegendBuilder(); assertTrue(lb1.equals(lb2)); assertFalse(lb1.equals(null)); lb1.setHeader("XYZ"); assertFalse(lb1.equals(lb2)); lb2.setHeader("XYZ"); assertTrue(lb1.equals(lb2)); lb1.setHeaderAlignment(HAlign.CENTER); assertFalse(lb1.equals(lb2)); lb2.setHeaderAlignment(HAlign.CENTER); assertTrue(lb1.equals(lb2)); lb1.setFooter("ABC"); assertFalse(lb1.equals(lb2)); lb2.setFooter("ABC"); assertTrue(lb1.equals(lb2)); lb1.setFooterAlignment(HAlign.CENTER); assertFalse(lb1.equals(lb2)); lb2.setFooterAlignment(HAlign.CENTER); assertTrue(lb1.equals(lb2)); } /** * Checks for serialization support. */ @Test public void testSerialization() { StandardLegendBuilder lb1 = new StandardLegendBuilder(); StandardLegendBuilder lb2 = (StandardLegendBuilder) TestUtils.serialized(lb1); assertTrue(lb1.equals(lb2)); } } orson-charts-2.1.0/src/test/java/org/jfree/chart3d/marker/000077500000000000000000000000001417331271500233225ustar00rootroot00000000000000orson-charts-2.1.0/src/test/java/org/jfree/chart3d/marker/CategoryMarkerTest.java000066400000000000000000000104451417331271500277500ustar00rootroot00000000000000/* =========================================================== * Orson Charts : a 3D chart library for the Java(tm) platform * =========================================================== * * (C)opyright 2013-2022, by David Gilbert. All rights reserved. * * https://github.com/jfree/orson-charts * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . * * [Oracle and Java are registered trademarks of Oracle and/or its affiliates. * Other names may be trademarks of their respective owners.] * * If you do not wish to be bound by the terms of the GPL, an alternative * commercial license can be purchased. For details, please see visit the * Orson Charts home page: * * http://www.object-refinery.com/orsoncharts/index.html * */ package org.jfree.chart3d.marker; import static org.junit.jupiter.api.Assertions.assertFalse; import static org.junit.jupiter.api.Assertions.assertTrue; import org.junit.jupiter.api.Test; import java.awt.BasicStroke; import java.awt.Color; import java.awt.Font; import org.jfree.chart3d.TestUtils; import org.jfree.chart3d.graphics2d.Anchor2D; /** * Tests for the {@link CategoryMarker} class. */ public class CategoryMarkerTest { /** * Some checks for the equals() method. */ @Test public void testEquals() { CategoryMarker cm1 = new CategoryMarker("A"); CategoryMarker cm2 = new CategoryMarker("A"); assertTrue(cm1.equals(cm2)); assertFalse(cm1.equals(null)); cm1 = new CategoryMarker("B"); assertFalse(cm1.equals(cm2)); cm2 = new CategoryMarker("B"); assertTrue(cm1.equals(cm2)); // CategoryMarkerType type; cm1.setType(CategoryMarkerType.LINE); assertFalse(cm1.equals(cm2)); cm2.setType(CategoryMarkerType.LINE); assertTrue(cm1.equals(cm2)); // String label; cm1.setLabel("ABC"); assertFalse(cm1.equals(cm2)); cm2.setLabel("ABC"); assertTrue(cm1.equals(cm2)); // Font font; cm1.setFont(new Font(Font.SERIF, Font.PLAIN, 15)); assertFalse(cm1.equals(cm2)); cm2.setFont(new Font(Font.SERIF, Font.PLAIN, 15)); assertTrue(cm1.equals(cm2)); // Color labelColor; cm1.setLabelColor(Color.CYAN); assertFalse(cm1.equals(cm2)); cm2.setLabelColor(Color.CYAN); assertTrue(cm1.equals(cm2)); // Anchor2D labelAnchor; cm1.setLabelAnchor(Anchor2D.BOTTOM_LEFT); assertFalse(cm1.equals(cm2)); cm2.setLabelAnchor(Anchor2D.BOTTOM_LEFT); assertTrue(cm1.equals(cm2)); // transient Stroke lineStroke; cm1.setLineStroke(new BasicStroke(0.6f)); assertFalse(cm1.equals(cm2)); cm2.setLineStroke(new BasicStroke(0.6f)); assertTrue(cm1.equals(cm2)); // Color lineColor; cm1.setLineColor(Color.YELLOW); assertFalse(cm1.equals(cm2)); cm2.setLineColor(Color.YELLOW); assertTrue(cm1.equals(cm2)); // Color fillColor; cm1.setFillColor(Color.GREEN); assertFalse(cm1.equals(cm2)); cm2.setFillColor(Color.GREEN); assertTrue(cm1.equals(cm2)); } /** * Checks for serialization support. */ @Test public void testSerialization() { CategoryMarker cm1 = new CategoryMarker("A"); cm1.setLabel("ABC"); cm1.setLabelAnchor(Anchor2D.BOTTOM_RIGHT); cm1.setLabelColor(Color.GREEN); cm1.setFillColor(Color.DARK_GRAY); cm1.setLineStroke(new BasicStroke(0.6f)); cm1.setLineColor(Color.RED); CategoryMarker cm2 = (CategoryMarker) TestUtils.serialized(cm1); assertTrue(cm1.equals(cm2)); } } orson-charts-2.1.0/src/test/java/org/jfree/chart3d/marker/NumberMarkerTest.java000066400000000000000000000045231417331271500274230ustar00rootroot00000000000000/* =========================================================== * Orson Charts : a 3D chart library for the Java(tm) platform * =========================================================== * * (C)opyright 2013-2022, by David Gilbert. All rights reserved. * * https://github.com/jfree/orson-charts * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . * * [Oracle and Java are registered trademarks of Oracle and/or its affiliates. * Other names may be trademarks of their respective owners.] * * If you do not wish to be bound by the terms of the GPL, an alternative * commercial license can be purchased. For details, please see visit the * Orson Charts home page: * * http://www.object-refinery.com/orsoncharts/index.html * */ package org.jfree.chart3d.marker; import static org.junit.jupiter.api.Assertions.assertFalse; import static org.junit.jupiter.api.Assertions.assertTrue; import org.junit.jupiter.api.Test; import org.jfree.chart3d.TestUtils; /** * Tests for the {@link NumberMarker} class. */ public class NumberMarkerTest { /** * Some checks for the equals() method. */ @Test public void testEquals() { NumberMarker nm1 = new NumberMarker(1.0); NumberMarker nm2 = new NumberMarker(1.0); assertTrue(nm1.equals(nm2)); assertFalse(nm1.equals(null)); nm1 = new NumberMarker(1.1); assertFalse(nm1.equals(nm2)); nm2 = new NumberMarker(1.1); assertTrue(nm1.equals(nm2)); } /** * Checks for serialization support. */ @Test public void testSerialization() { NumberMarker nm1 = new NumberMarker(1.0); NumberMarker nm2 = (NumberMarker) TestUtils.serialized(nm1); assertTrue(nm1.equals(nm2)); } } orson-charts-2.1.0/src/test/java/org/jfree/chart3d/marker/RangeMarkerTest.java000066400000000000000000000045401417331271500272260ustar00rootroot00000000000000/* =========================================================== * Orson Charts : a 3D chart library for the Java(tm) platform * =========================================================== * * (C)opyright 2013-2022, by David Gilbert. All rights reserved. * * https://github.com/jfree/orson-charts * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . * * [Oracle and Java are registered trademarks of Oracle and/or its affiliates. * Other names may be trademarks of their respective owners.] * * If you do not wish to be bound by the terms of the GPL, an alternative * commercial license can be purchased. For details, please see visit the * Orson Charts home page: * * http://www.object-refinery.com/orsoncharts/index.html * */ package org.jfree.chart3d.marker; import static org.junit.jupiter.api.Assertions.assertFalse; import static org.junit.jupiter.api.Assertions.assertTrue; import org.junit.jupiter.api.Test; import org.jfree.chart3d.TestUtils; /** * Tests for the {@link RangeMarker} class. */ public class RangeMarkerTest { /** * Some checks for the equals() method. */ @Test public void testEquals() { RangeMarker rm1 = new RangeMarker(1.0, 2.0); RangeMarker rm2 = new RangeMarker(1.0, 2.0); assertTrue(rm1.equals(rm2)); assertFalse(rm1.equals(null)); rm1 = new RangeMarker(1.1, 2.0); assertFalse(rm1.equals(rm2)); rm2 = new RangeMarker(1.1, 2.0); assertTrue(rm1.equals(rm2)); } /** * Checks for serialization support. */ @Test public void testSerialization() { RangeMarker rm1 = new RangeMarker(1.0, 2.0); RangeMarker rm2 = (RangeMarker) TestUtils.serialized(rm1); assertTrue(rm1.equals(rm2)); } } orson-charts-2.1.0/src/test/java/org/jfree/chart3d/plot/000077500000000000000000000000001417331271500230175ustar00rootroot00000000000000orson-charts-2.1.0/src/test/java/org/jfree/chart3d/plot/CategoryPlot3DTest.java000066400000000000000000000130601417331271500273250ustar00rootroot00000000000000/* =========================================================== * Orson Charts : a 3D chart library for the Java(tm) platform * =========================================================== * * (C)opyright 2013-2022, by David Gilbert. All rights reserved. * * https://github.com/jfree/orson-charts * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . * * [Oracle and Java are registered trademarks of Oracle and/or its affiliates. * Other names may be trademarks of their respective owners.] * * If you do not wish to be bound by the terms of the GPL, an alternative * commercial license can be purchased. For details, please see visit the * Orson Charts home page: * * http://www.object-refinery.com/orsoncharts/index.html * */ package org.jfree.chart3d.plot; import org.junit.jupiter.api.Test; import java.awt.BasicStroke; import java.awt.Color; import java.awt.GradientPaint; import org.jfree.chart3d.TestUtils; import org.jfree.chart3d.axis.NumberAxis3D; import org.jfree.chart3d.axis.StandardCategoryAxis3D; import org.jfree.chart3d.data.category.CategoryDataset3D; import org.jfree.chart3d.data.category.StandardCategoryDataset3D; import org.jfree.chart3d.label.StandardCategoryLabelGenerator; import org.jfree.chart3d.renderer.category.BarRenderer3D; import static org.junit.jupiter.api.Assertions.*; /** * Tests for the {@link CategoryPlot3D} class. */ public class CategoryPlot3DTest { @Test public void testEquals() { StandardCategoryDataset3D d1 = new StandardCategoryDataset3D<>(); BarRenderer3D r1 = new BarRenderer3D(); CategoryPlot3D p1 = new CategoryPlot3D(d1, r1, new StandardCategoryAxis3D("R"), new StandardCategoryAxis3D("C"), new NumberAxis3D("N")); StandardCategoryDataset3D d2 = new StandardCategoryDataset3D<>(); BarRenderer3D r2 = new BarRenderer3D(); CategoryPlot3D p2 = new CategoryPlot3D(d2, r2, new StandardCategoryAxis3D("R"), new StandardCategoryAxis3D("C"), new NumberAxis3D("N")); assertEquals(p1, p2); assertNotEquals(null, p1); p1.setGridlinesVisibleForValues(false); assertNotEquals(p1, p2); p2.setGridlinesVisibleForValues(false); assertEquals(p1, p2); p1.setGridlinePaintForValues(Color.RED); assertNotEquals(p1, p2); p2.setGridlinePaintForValues(Color.RED); assertEquals(p1, p2); p1.setGridlineStrokeForValues(new BasicStroke(0.5f)); assertNotEquals(p1, p2); p2.setGridlineStrokeForValues(new BasicStroke(0.5f)); assertEquals(p1, p2); p1.setGridlinesVisibleForRows(true); assertNotEquals(p1, p2); p2.setGridlinesVisibleForRows(true); assertEquals(p1, p2); p1.setGridlinePaintForRows(Color.GREEN); assertNotEquals(p1, p2); p2.setGridlinePaintForRows(Color.GREEN); assertEquals(p1, p2); p1.setGridlineStrokeForRows(new BasicStroke(0.6f)); assertNotEquals(p1, p2); p2.setGridlineStrokeForRows(new BasicStroke(0.6f)); assertEquals(p1, p2); p1.setLegendLabelGenerator(new StandardCategoryLabelGenerator<>("%s XX")); assertNotEquals(p1, p2); p2.setLegendLabelGenerator(new StandardCategoryLabelGenerator<>("%s XX")); assertEquals(p1, p2); p1.setYDimensionOverride(123.0); assertNotEquals(p1, p2); p2.setYDimensionOverride(123.0); assertEquals(p1, p2); } /** * Checks for serialization. */ @Test public void testSerialization() { CategoryPlot3D p1 = createCategory3DPlot(); CategoryPlot3D p2 = (CategoryPlot3D) TestUtils.serialized(p1); assertEquals(p1, p2); p1.setGridlinePaintForRows(new GradientPaint(1f, 2f, Color.RED, 3f, 4f, Color.BLUE)); p2 = (CategoryPlot3D) TestUtils.serialized(p1); assertEquals(p1, p2); p1.setGridlinePaintForColumns(new GradientPaint(5f, 6f, Color.GRAY, 7f, 8f, Color.YELLOW)); p2 = (CategoryPlot3D) TestUtils.serialized(p1); assertEquals(p1, p2); p1.setGridlinePaintForValues(new GradientPaint(9f, 10f, Color.GREEN, 11f, 12f, Color.LIGHT_GRAY)); p2 = (CategoryPlot3D) TestUtils.serialized(p1); assertEquals(p1, p2); } private CategoryPlot3D createCategory3DPlot() { CategoryDataset3D dataset = new StandardCategoryDataset3D<>(); BarRenderer3D renderer = new BarRenderer3D(); StandardCategoryAxis3D rowAxis = new StandardCategoryAxis3D("rowAxis"); StandardCategoryAxis3D colAxis = new StandardCategoryAxis3D("colAxis"); NumberAxis3D valueAxis = new NumberAxis3D("Value"); return new CategoryPlot3D(dataset, renderer, rowAxis, colAxis, valueAxis); } } orson-charts-2.1.0/src/test/java/org/jfree/chart3d/plot/PiePlot3DTest.java000066400000000000000000000154671417331271500263020ustar00rootroot00000000000000/* =========================================================== * Orson Charts : a 3D chart library for the Java(tm) platform * =========================================================== * * (C)opyright 2013-2022, by David Gilbert. All rights reserved. * * https://github.com/jfree/orson-charts * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . * * [Oracle and Java are registered trademarks of Oracle and/or its affiliates. * Other names may be trademarks of their respective owners.] * * If you do not wish to be bound by the terms of the GPL, an alternative * commercial license can be purchased. For details, please see visit the * Orson Charts home page: * * http://www.object-refinery.com/orsoncharts/index.html * */ package org.jfree.chart3d.plot; import static org.junit.jupiter.api.Assertions.assertFalse; import static org.junit.jupiter.api.Assertions.assertNotNull; import static org.junit.jupiter.api.Assertions.assertNull; import static org.junit.jupiter.api.Assertions.assertTrue; import static org.junit.jupiter.api.Assertions.assertEquals; import org.junit.jupiter.api.Test; import java.awt.Color; import java.awt.Font; import org.jfree.chart3d.Chart3D; import org.jfree.chart3d.Chart3DFactory; import org.jfree.chart3d.TestUtils; import org.jfree.chart3d.data.StandardPieDataset3D; import org.jfree.chart3d.label.StandardPieLabelGenerator; /** * Some tests for the {@link PiePlot3D} class. */ public class PiePlot3DTest implements Plot3DChangeListener { @Test public void checkSetRadiusFiresChangeEvent() { PiePlot3D plot = createPiePlot3D(); plot.addChangeListener(this); assertNull(this.lastEvent); plot.setRadius(10.2); assertNotNull(this.lastEvent); this.lastEvent = null; } @Test public void checkSetDepthFiresChangeEvent() { PiePlot3D plot = createPiePlot3D(); plot.addChangeListener(this); assertNull(this.lastEvent); plot.setDepth(0.123); assertNotNull(this.lastEvent); this.lastEvent = null; } @Test @SuppressWarnings("unchecked") public void checkSetDatasetFiresChangeEvent() { PiePlot3D plot = createPiePlot3D(); plot.addChangeListener(this); assertNull(this.lastEvent); plot.setDataset(createNewDataset()); assertNotNull(this.lastEvent); this.lastEvent = null; } @Test @SuppressWarnings("unchecked") public void checkSetDatasetRemovesPreviousListener() { StandardPieDataset3D dataset1 = createNewDataset(); PiePlot3D plot = new PiePlot3D(dataset1); assertTrue(dataset1.hasListener(plot)); StandardPieDataset3D dataset2 = createNewDataset(); plot.setDataset(dataset2); assertFalse(dataset1.hasListener(plot)); assertTrue(dataset2.hasListener(plot)); } /** * Check that all the required fields are taken into a account by the * equals() method. */ @Test public void checkEquals() { StandardPieDataset3D dataset1 = createNewDataset(); PiePlot3D p1 = new PiePlot3D(dataset1); PiePlot3D p2 = new PiePlot3D(dataset1); assertEquals(p1, p2); // radius p1.setRadius(12.3); assertFalse(p1.equals(p2)); p2.setRadius(12.3); assertTrue(p1.equals(p2)); // depth p1.setDepth(3.21); assertFalse(p1.equals(p2)); p2.setDepth(3.21); assertTrue(p1.equals(p2)); // section label generator p1.setSectionLabelGenerator(new StandardPieLabelGenerator("Key: %s")); assertFalse(p1.equals(p2)); p2.setSectionLabelGenerator(new StandardPieLabelGenerator("Key: %s")); assertTrue(p1.equals(p2)); // section color source p1.setSectionColorSource(new StandardColorSource(Color.CYAN)); assertFalse(p1.equals(p2)); p2.setSectionColorSource(new StandardColorSource(Color.CYAN)); assertTrue(p1.equals(p2)); // section label font source p1.setSectionLabelFontSource(new StandardFontSource(new Font("Dialog", Font.PLAIN, 9))); assertFalse(p1.equals(p2)); p2.setSectionLabelFontSource(new StandardFontSource(new Font("Dialog", Font.PLAIN, 9))); assertTrue(p1.equals(p2)); // section label color source p1.setSectionLabelColorSource(new StandardColorSource(Color.BLUE)); assertFalse(p1.equals(p2)); p2.setSectionLabelColorSource(new StandardColorSource(Color.BLUE)); assertTrue(p1.equals(p2)); // legend label generator p1.setLegendLabelGenerator(new StandardPieLabelGenerator("Key: %s")); assertFalse(p1.equals(p2)); p2.setLegendLabelGenerator(new StandardPieLabelGenerator("Key: %s")); assertTrue(p1.equals(p2)); // tool tip generator p1.setToolTipGenerator(new StandardPieLabelGenerator("Tool tip: %s")); assertFalse(p1.equals(p2)); p2.setToolTipGenerator(new StandardPieLabelGenerator("Tool tip: %s")); assertTrue(p1.equals(p2)); // segments p1.setSegmentCount(123); assertFalse(p1.equals(p2)); p2.setSegmentCount(123); assertTrue(p1.equals(p2)); } /** * A check for serialization. */ @Test public void testSerializationPieChart() { Chart3D c1 = Chart3DFactory.createPieChart("title", "subtitle", createNewDataset()); Chart3D c2 = (Chart3D) TestUtils.serialized(c1); assertEquals(c1, c2); } /** * Creates and returns a new dataset (it is important for the tests that * this method always returns a new dataset). * * @return A new dataset. */ private StandardPieDataset3D createNewDataset() { StandardPieDataset3D dataset = new StandardPieDataset3D<>(); dataset.add("A", 123.4); return dataset; } private PiePlot3D createPiePlot3D() { return new PiePlot3D(createNewDataset()); } private Plot3DChangeEvent lastEvent = null; @Override public void plotChanged(Plot3DChangeEvent event) { this.lastEvent = event; } } orson-charts-2.1.0/src/test/java/org/jfree/chart3d/plot/StandardColorSourceTest.java000066400000000000000000000060001417331271500304360ustar00rootroot00000000000000/* =========================================================== * Orson Charts : a 3D chart library for the Java(tm) platform * =========================================================== * * (C)opyright 2013-2022, by David Gilbert. All rights reserved. * * https://github.com/jfree/orson-charts * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . * * [Oracle and Java are registered trademarks of Oracle and/or its affiliates. * Other names may be trademarks of their respective owners.] * * If you do not wish to be bound by the terms of the GPL, an alternative * commercial license can be purchased. For details, please see visit the * Orson Charts home page: * * http://www.object-refinery.com/orsoncharts/index.html * */ package org.jfree.chart3d.plot; import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertFalse; import static org.junit.jupiter.api.Assertions.assertTrue; import static org.junit.jupiter.api.Assertions.fail; import java.awt.Color; import org.junit.jupiter.api.Test; /** * Some tests for the {@link StandardColorSource} class. */ public class StandardColorSourceTest { @Test public void testConstructors() { StandardColorSource scs = new StandardColorSource<>(Color.RED); assertEquals(Color.RED, scs.getColor("A")); scs = new StandardColorSource<>(Color.RED, Color.GREEN, Color.BLUE); assertEquals(Color.RED, scs.getColor("A")); assertEquals(Color.GREEN, scs.getColor("B")); assertEquals(Color.BLUE, scs.getColor("C")); try { scs = new StandardColorSource<>((Color[]) null); fail("Should have thrown an exception."); } catch (IllegalArgumentException e) { // expected } try { scs = new StandardColorSource<>(Color.RED, null); fail("Should have thrown an exception"); } catch (IllegalArgumentException e) { // expected } } @Test public void testEquals() { StandardColorSource scs1 = new StandardColorSource<>(Color.RED); StandardColorSource scs2 = new StandardColorSource<>(Color.RED); assertTrue(scs1.equals(scs2)); scs1.setColor("A", Color.YELLOW); assertFalse(scs1.equals(scs2)); scs2.setColor("A", Color.YELLOW); assertTrue(scs1.equals(scs2)); } } orson-charts-2.1.0/src/test/java/org/jfree/chart3d/plot/XYZPlotTest.java000066400000000000000000000176711417331271500260670ustar00rootroot00000000000000/* =========================================================== * Orson Charts : a 3D chart library for the Java(tm) platform * =========================================================== * * (C)opyright 2013-2022, by David Gilbert. All rights reserved. * * https://github.com/jfree/orson-charts * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . * * [Oracle and Java are registered trademarks of Oracle and/or its affiliates. * Other names may be trademarks of their respective owners.] * * If you do not wish to be bound by the terms of the GPL, an alternative * commercial license can be purchased. For details, please see visit the * Orson Charts home page: * * http://www.object-refinery.com/orsoncharts/index.html * */ package org.jfree.chart3d.plot; import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertFalse; import static org.junit.jupiter.api.Assertions.assertNotEquals; import static org.junit.jupiter.api.Assertions.assertNotNull; import static org.junit.jupiter.api.Assertions.assertNull; import static org.junit.jupiter.api.Assertions.assertTrue; import org.jfree.chart3d.data.xyz.XYZSeries; import org.junit.jupiter.api.Test; import java.awt.BasicStroke; import java.awt.Color; import java.awt.GradientPaint; import org.jfree.chart3d.TestUtils; import org.jfree.chart3d.axis.NumberAxis3D; import org.jfree.chart3d.axis.ValueAxis3D; import org.jfree.chart3d.data.Range; import org.jfree.chart3d.data.xyz.XYZDataset; import org.jfree.chart3d.data.xyz.XYZSeriesCollection; import org.jfree.chart3d.graphics3d.Dimension3D; import org.jfree.chart3d.label.StandardXYZLabelGenerator; import org.jfree.chart3d.renderer.xyz.ScatterXYZRenderer; import org.jfree.chart3d.renderer.xyz.XYZRenderer; /** * Checks for the {@link XYZPlot} class. */ public class XYZPlotTest implements Plot3DChangeListener { @Test public void checkSetDatasetFiresChangeEvent() { XYZPlot plot = createXYZPlot(); plot.addChangeListener(this); assertNull(this.lastEvent); plot.setDataset(createNewDataset()); assertNotNull(this.lastEvent); this.lastEvent = null; } @Test public void checkSetDatasetRemovesPreviousListener() { XYZDataset dataset1 = createNewDataset(); XYZPlot plot = createXYZPlot(); plot.setDataset(dataset1); assertTrue(dataset1.hasListener(plot)); XYZDataset dataset2 = createNewDataset(); plot.setDataset(dataset2); assertFalse(dataset1.hasListener(plot)); assertTrue(dataset2.hasListener(plot)); } @Test public void checkEquals() { XYZPlot p1 = createXYZPlot(); XYZPlot p2 = createXYZPlot(); assertEquals(p1, p2); p1.setDimensions(new Dimension3D(1, 2, 3)); assertNotEquals(p1, p2); p2.setDimensions(new Dimension3D(1, 2, 3)); assertEquals(p1, p2); p1.setGridlinesVisibleX(false); assertNotEquals(p1, p2); p2.setGridlinesVisibleX(false); assertEquals(p1, p2); p1.setGridlinePaintX(Color.YELLOW); assertNotEquals(p1, p2); p2.setGridlinePaintX(Color.YELLOW); assertEquals(p1, p2); p1.setGridlineStrokeX(new BasicStroke(0.3f)); assertNotEquals(p1, p2); p2.setGridlineStrokeX(new BasicStroke(0.3f)); assertEquals(p1, p2); p1.setGridlinesVisibleY(false); assertNotEquals(p1, p2); p2.setGridlinesVisibleY(false); assertEquals(p1, p2); p1.setGridlinePaintY(Color.GREEN); assertNotEquals(p1, p2); p2.setGridlinePaintY(Color.GREEN); assertEquals(p1, p2); p1.setGridlineStrokeY(new BasicStroke(0.36f)); assertNotEquals(p1, p2); p2.setGridlineStrokeY(new BasicStroke(0.36f)); assertEquals(p1, p2); p1.setGridlinesVisibleZ(false); assertNotEquals(p1, p2); p2.setGridlinesVisibleZ(false); assertEquals(p1, p2); p1.setGridlinePaintZ(Color.BLUE); assertNotEquals(p1, p2); p2.setGridlinePaintZ(Color.BLUE); assertEquals(p1, p2); p1.setGridlineStrokeZ(new BasicStroke(0.6f)); assertNotEquals(p1, p2); p2.setGridlineStrokeZ(new BasicStroke(0.6f)); assertEquals(p1, p2); p1.setLegendLabelGenerator(new StandardXYZLabelGenerator("%s XX")); assertNotEquals(p1, p2); p2.setLegendLabelGenerator(new StandardXYZLabelGenerator("%s XX")); assertEquals(p1, p2); } /** * Checks for serialization. */ @Test public void testSerialization() { XYZPlot p1 = createXYZPlot(); XYZPlot p2 = (XYZPlot) TestUtils.serialized(p1); assertEquals(p1, p2); p1.setGridlinePaintX(new GradientPaint(1f, 2f, Color.RED, 3f, 4f, Color.BLUE)); p2 = (XYZPlot) TestUtils.serialized(p1); assertEquals(p1, p2); p1.setGridlinePaintY(new GradientPaint(5f, 6f, Color.GRAY, 7f, 8f, Color.YELLOW)); p2 = (XYZPlot) TestUtils.serialized(p1); assertEquals(p1, p2); p1.setGridlinePaintZ(new GradientPaint(9f, 10f, Color.GREEN, 11f, 12f, Color.LIGHT_GRAY)); p2 = (XYZPlot) TestUtils.serialized(p1); assertEquals(p1, p2); } /** * https://github.com/jfree/orson-charts/issues/9 */ @Test public void testBug9() { XYZSeries series = new XYZSeries<>("S1"); series.add(5.0, 6.0, 7.0); series.add(8.0, 9.0, 10.0); XYZSeriesCollection dataset = new XYZSeriesCollection<>(); dataset.add(series); NumberAxis3D xAxis = new NumberAxis3D("X", new Range(0, 10)); NumberAxis3D yAxis = new NumberAxis3D("Y", new Range(0, 10)); NumberAxis3D zAxis = new NumberAxis3D("Z", new Range(0, 10)); XYZRenderer renderer = new ScatterXYZRenderer(); XYZPlot plot = new XYZPlot(dataset, renderer, xAxis, yAxis, zAxis); assertEquals(new Range(4.85, 8.15), xAxis.getRange()); xAxis.setAutoRangeIncludeZero(true); assertEquals(new Range(0.0, 8.15), xAxis.getRange()); assertEquals(new Range(5.85, 9.15), yAxis.getRange()); yAxis.setAutoRangeIncludeZero(true); assertEquals(new Range(0.0, 9.15), yAxis.getRange()); assertEquals(new Range(6.85, 10.15), zAxis.getRange()); zAxis.setAutoRangeIncludeZero(true); assertEquals(new Range(0.0, 10.15), zAxis.getRange()); } /** * Returns a new dataset. * * @return A new dataset. */ private XYZDataset createNewDataset() { return new XYZSeriesCollection<>(); } /** * Returns a new plot with no assigned dataset. * * @return A new plot. */ private XYZPlot createXYZPlot() { ValueAxis3D xAxis = new NumberAxis3D("X", new Range(0, 10)); ValueAxis3D yAxis = new NumberAxis3D("Y", new Range(0, 10)); ValueAxis3D zAxis = new NumberAxis3D("Z", new Range(0, 10)); XYZRenderer renderer = new ScatterXYZRenderer(); return new XYZPlot(createNewDataset(), renderer, xAxis, yAxis, zAxis); } private Plot3DChangeEvent lastEvent = null; @Override public void plotChanged(Plot3DChangeEvent event) { this.lastEvent = event; } } orson-charts-2.1.0/src/test/java/org/jfree/chart3d/renderer/000077500000000000000000000000001417331271500236475ustar00rootroot00000000000000orson-charts-2.1.0/src/test/java/org/jfree/chart3d/renderer/FixedColorScaleTest.java000066400000000000000000000045241417331271500303650ustar00rootroot00000000000000/* =========================================================== * Orson Charts : a 3D chart library for the Java(tm) platform * =========================================================== * * (C)opyright 2013-2022, by David Gilbert. All rights reserved. * * https://github.com/jfree/orson-charts * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . * * [Oracle and Java are registered trademarks of Oracle and/or its affiliates. * Other names may be trademarks of their respective owners.] * * If you do not wish to be bound by the terms of the GPL, an alternative * commercial license can be purchased. For details, please see visit the * Orson Charts home page: * * http://www.object-refinery.com/orsoncharts/index.html * */ package org.jfree.chart3d.renderer; import static org.junit.jupiter.api.Assertions.assertFalse; import static org.junit.jupiter.api.Assertions.assertTrue; import org.junit.jupiter.api.Test; import org.jfree.chart3d.TestUtils; import java.awt.Color; /** * Tests for the {@link FixedColorScale} class. */ public class FixedColorScaleTest { @Test public void testEquals() { FixedColorScale fcs1 = new FixedColorScale(Color.YELLOW); FixedColorScale fcs2 = new FixedColorScale(Color.YELLOW); assertTrue(fcs1.equals(fcs2)); assertFalse(fcs1.equals(null)); fcs1 = new FixedColorScale(Color.BLUE); assertFalse(fcs1.equals(fcs2)); fcs2 = new FixedColorScale(Color.BLUE); assertTrue(fcs1.equals(fcs2)); } @Test public void testSerialization() { FixedColorScale fcs1 = new FixedColorScale(Color.YELLOW); FixedColorScale fcs2 = (FixedColorScale) TestUtils.serialized(fcs1); assertTrue(fcs1.equals(fcs2)); } } orson-charts-2.1.0/src/test/java/org/jfree/chart3d/renderer/GradientColorScaleTest.java000066400000000000000000000060041417331271500310560ustar00rootroot00000000000000/* =========================================================== * Orson Charts : a 3D chart library for the Java(tm) platform * =========================================================== * * (C)opyright 2013-2022, by David Gilbert. All rights reserved. * * https://github.com/jfree/orson-charts * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . * * [Oracle and Java are registered trademarks of Oracle and/or its affiliates. * Other names may be trademarks of their respective owners.] * * If you do not wish to be bound by the terms of the GPL, an alternative * commercial license can be purchased. For details, please see visit the * Orson Charts home page: * * http://www.object-refinery.com/orsoncharts/index.html * */ package org.jfree.chart3d.renderer; import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertFalse; import static org.junit.jupiter.api.Assertions.assertTrue; import org.junit.jupiter.api.Test; import java.awt.Color; import org.jfree.chart3d.TestUtils; import org.jfree.chart3d.data.Range; /** * Tests for the {@link GradientColorScale} class. */ public class GradientColorScaleTest { @Test public void testGeneral() { GradientColorScale gcs = new GradientColorScale(new Range(0.0, 1.0), Color.YELLOW, Color.RED); assertEquals(Color.YELLOW, gcs.valueToColor(0.0)); assertEquals(Color.RED, gcs.valueToColor(1.0)); } @Test public void testEquals() { GradientColorScale gcs1 = new GradientColorScale(new Range(0.0, 1.0), Color.YELLOW, Color.RED); GradientColorScale gcs2 = new GradientColorScale(new Range(0.0, 1.0), Color.YELLOW, Color.RED); assertTrue(gcs1.equals(gcs2)); assertFalse(gcs1.equals(null)); gcs1 = new GradientColorScale(new Range(0.0, 1.0), Color.BLUE, Color.WHITE); assertFalse(gcs1.equals(gcs2)); gcs2 = new GradientColorScale(new Range(0.0, 1.0), Color.BLUE, Color.WHITE); assertTrue(gcs1.equals(gcs2)); } @Test public void testSerialization() { GradientColorScale gcs1 = new GradientColorScale(new Range(0.0, 1.0), Color.YELLOW, Color.RED); GradientColorScale gcs2 = (GradientColorScale) TestUtils.serialized( gcs1); assertTrue(gcs1.equals(gcs2)); } } orson-charts-2.1.0/src/test/java/org/jfree/chart3d/renderer/RainbowScaleTest.java000066400000000000000000000042441417331271500277270ustar00rootroot00000000000000/* =========================================================== * Orson Charts : a 3D chart library for the Java(tm) platform * =========================================================== * * (C)opyright 2013-2022, by David Gilbert. All rights reserved. * * https://github.com/jfree/orson-charts * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . * * [Oracle and Java are registered trademarks of Oracle and/or its affiliates. * Other names may be trademarks of their respective owners.] * * If you do not wish to be bound by the terms of the GPL, an alternative * commercial license can be purchased. For details, please see visit the * Orson Charts home page: * * http://www.object-refinery.com/orsoncharts/index.html * */ package org.jfree.chart3d.renderer; import static org.junit.jupiter.api.Assertions.assertFalse; import static org.junit.jupiter.api.Assertions.assertTrue; import org.junit.jupiter.api.Test; import org.jfree.chart3d.TestUtils; import org.jfree.chart3d.data.Range; /** * Tests for the {@link RainbowScale} class. */ public class RainbowScaleTest { @Test public void testEquals() { RainbowScale rs1 = new RainbowScale(new Range(5.0, 10.0)); RainbowScale rs2 = new RainbowScale(new Range(5.0, 10.0)); assertTrue(rs1.equals(rs2)); assertFalse(rs1.equals(null)); } @Test public void testSerialization() { RainbowScale rs1 = new RainbowScale(new Range(5.0, 10.0)); RainbowScale rs2 = (RainbowScale) TestUtils.serialized(rs1); assertTrue(rs1.equals(rs2)); } } orson-charts-2.1.0/src/test/java/org/jfree/chart3d/renderer/category/000077500000000000000000000000001417331271500254645ustar00rootroot00000000000000orson-charts-2.1.0/src/test/java/org/jfree/chart3d/renderer/category/AreaRenderer3DTest.java000066400000000000000000000053031417331271500317160ustar00rootroot00000000000000/* =========================================================== * Orson Charts : a 3D chart library for the Java(tm) platform * =========================================================== * * (C)opyright 2013-2022, by David Gilbert. All rights reserved. * * https://github.com/jfree/orson-charts * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . * * [Oracle and Java are registered trademarks of Oracle and/or its affiliates. * Other names may be trademarks of their respective owners.] * * If you do not wish to be bound by the terms of the GPL, an alternative * commercial license can be purchased. For details, please see visit the * Orson Charts home page: * * http://www.object-refinery.com/orsoncharts/index.html * */ package org.jfree.chart3d.renderer.category; import static org.junit.jupiter.api.Assertions.assertFalse; import static org.junit.jupiter.api.Assertions.assertTrue; import java.awt.Color; import org.junit.jupiter.api.Test; import org.jfree.chart3d.TestUtils; /** * Tests for the {@link AreaRenderer3D} class. */ public class AreaRenderer3DTest { @Test public void testEquals() { AreaRenderer3D r1 = new AreaRenderer3D(); AreaRenderer3D r2 = new AreaRenderer3D(); assertTrue(r1.equals(r2)); assertFalse(r1.equals(null)); // base r1.setBase(9.9); assertFalse(r1.equals(r2)); r2.setBase(9.9); assertTrue(r1.equals(r2)); // baseColor r1.setBaseColor(Color.BLUE); assertFalse(r1.equals(r2)); r2.setBaseColor(Color.BLUE); assertTrue(r1.equals(r2)); // depth r1.setDepth(8.8); assertFalse(r1.equals(r2)); r2.setDepth(8.8); assertTrue(r1.equals(r2)); // notify r1.setNotify(false); assertFalse(r1.equals(r2)); r2.setNotify(false); assertTrue(r1.equals(r2)); } @Test public void testSerialization() { AreaRenderer3D r1 = new AreaRenderer3D(); AreaRenderer3D r2 = (AreaRenderer3D) TestUtils.serialized(r1); assertTrue(r1.equals(r2)); } } orson-charts-2.1.0/src/test/java/org/jfree/chart3d/renderer/category/BarRenderer3DTest.java000066400000000000000000000066401417331271500315570ustar00rootroot00000000000000/* =========================================================== * Orson Charts : a 3D chart library for the Java(tm) platform * =========================================================== * * (C)opyright 2013-2022, by David Gilbert. All rights reserved. * * https://github.com/jfree/orson-charts * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . * * [Oracle and Java are registered trademarks of Oracle and/or its affiliates. * Other names may be trademarks of their respective owners.] * * If you do not wish to be bound by the terms of the GPL, an alternative * commercial license can be purchased. For details, please see visit the * Orson Charts home page: * * http://www.object-refinery.com/orsoncharts/index.html * */ package org.jfree.chart3d.renderer.category; import static org.junit.jupiter.api.Assertions.assertFalse; import static org.junit.jupiter.api.Assertions.assertTrue; import org.junit.jupiter.api.Test; import java.awt.Color; import org.jfree.chart3d.TestUtils; /** * Tests for the {@link BarRenderer3D} class. */ public class BarRenderer3DTest { @Test public void testEquals() { BarRenderer3D r1 = new BarRenderer3D(); BarRenderer3D r2 = new BarRenderer3D(); assertTrue(r1.equals(r2)); assertFalse(r1.equals(null)); r1.setBase(-1.0); assertFalse(r1.equals(r2)); r2.setBase(-1.0); assertTrue(r1.equals(r2)); r1.setBarXWidth(1.1); assertFalse(r1.equals(r2)); r2.setBarXWidth(1.1); assertTrue(r1.equals(r2)); r1.setBarZWidth(2.2); assertFalse(r1.equals(r2)); r2.setBarZWidth(2.2); assertTrue(r1.equals(r2)); // baseColorSource r1.setBaseColorSource(null); assertFalse(r1.equals(r2)); r2.setBaseColorSource(null); assertTrue(r1.equals(r2)); r1.setBaseColorSource(new StandardCategoryColorSource(Color.CYAN)); assertFalse(r1.equals(r2)); r2.setBaseColorSource(new StandardCategoryColorSource(Color.CYAN)); assertTrue(r1.equals(r2)); // topColorSource r1.setTopColorSource(null); assertFalse(r1.equals(r2)); r2.setTopColorSource(null); assertTrue(r1.equals(r2)); r1.setTopColorSource(new StandardCategoryColorSource(Color.YELLOW)); assertFalse(r1.equals(r2)); r2.setTopColorSource(new StandardCategoryColorSource(Color.YELLOW)); assertTrue(r1.equals(r2)); // notify r1.setNotify(false); assertFalse(r1.equals(r2)); r2.setNotify(false); assertTrue(r1.equals(r2)); } @Test public void testSerialization() { BarRenderer3D r1 = new BarRenderer3D(); BarRenderer3D r2 = (BarRenderer3D) TestUtils.serialized(r1); assertTrue(r1.equals(r2)); } }orson-charts-2.1.0/src/test/java/org/jfree/chart3d/renderer/category/LineRenderer3DTest.java000066400000000000000000000053401417331271500317360ustar00rootroot00000000000000/* =========================================================== * Orson Charts : a 3D chart library for the Java(tm) platform * =========================================================== * * (C)opyright 2013-2022, by David Gilbert. All rights reserved. * * https://github.com/jfree/orson-charts * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . * * [Oracle and Java are registered trademarks of Oracle and/or its affiliates. * Other names may be trademarks of their respective owners.] * * If you do not wish to be bound by the terms of the GPL, an alternative * commercial license can be purchased. For details, please see visit the * Orson Charts home page: * * http://www.object-refinery.com/orsoncharts/index.html * */ package org.jfree.chart3d.renderer.category; import static org.junit.jupiter.api.Assertions.assertFalse; import static org.junit.jupiter.api.Assertions.assertTrue; import org.junit.jupiter.api.Test; import org.jfree.chart3d.TestUtils; import java.awt.Color; /** * Tests for the {@link LineRenderer3D} class. */ public class LineRenderer3DTest { @Test public void testEquals() { LineRenderer3D r1 = new LineRenderer3D(); LineRenderer3D r2 = new LineRenderer3D(); assertTrue(r1.equals(r2)); assertFalse(r1.equals(null)); r1.setLineWidth(1.1); assertFalse(r1.equals(r2)); r2.setLineWidth(1.1); assertTrue(r1.equals(r2)); r1.setLineHeight(2.2); assertFalse(r1.equals(r2)); r2.setLineHeight(2.2); assertTrue(r1.equals(r2)); r1.setClipColorSource(new StandardCategoryColorSource(Color.BLUE)); assertFalse(r1.equals(r2)); r2.setClipColorSource(new StandardCategoryColorSource(Color.BLUE)); assertTrue(r1.equals(r2)); // notify r1.setNotify(false); assertFalse(r1.equals(r2)); r2.setNotify(false); assertTrue(r1.equals(r2)); } @Test public void testSerialization() { LineRenderer3D r1 = new LineRenderer3D(); LineRenderer3D r2 = (LineRenderer3D) TestUtils.serialized(r1); assertTrue(r1.equals(r2)); } }orson-charts-2.1.0/src/test/java/org/jfree/chart3d/renderer/category/StackedBarRenderer3DTest.java000066400000000000000000000050161417331271500330520ustar00rootroot00000000000000/* =========================================================== * Orson Charts : a 3D chart library for the Java(tm) platform * =========================================================== * * (C)opyright 2013-2022, by David Gilbert. All rights reserved. * * https://github.com/jfree/orson-charts * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . * * [Oracle and Java are registered trademarks of Oracle and/or its affiliates. * Other names may be trademarks of their respective owners.] * * If you do not wish to be bound by the terms of the GPL, an alternative * commercial license can be purchased. For details, please see visit the * Orson Charts home page: * * http://www.object-refinery.com/orsoncharts/index.html * */ package org.jfree.chart3d.renderer.category; import static org.junit.jupiter.api.Assertions.assertFalse; import static org.junit.jupiter.api.Assertions.assertTrue; import org.junit.jupiter.api.Test; import org.jfree.chart3d.TestUtils; /** * Tests for the {@link StackedBarRenderer3D} class. */ public class StackedBarRenderer3DTest { /** * Some checks for the equals() method. */ @Test public void testEquals() { StackedBarRenderer3D r1 = new StackedBarRenderer3D(); StackedBarRenderer3D r2 = new StackedBarRenderer3D(); assertTrue(r1.equals(r2)); assertFalse(r1.equals(null)); // notify r1.setNotify(false); assertFalse(r1.equals(r2)); r2.setNotify(false); assertTrue(r1.equals(r2)); // ensure that we distinguish from the base class assertFalse(r1.equals(new BarRenderer3D())); } /** * Some checks for serialization. */ @Test public void testSerialization() { StackedBarRenderer3D r1 = new StackedBarRenderer3D(); StackedBarRenderer3D r2 = (StackedBarRenderer3D) TestUtils.serialized(r1); assertTrue(r1.equals(r2)); } } StandardCategoryColorSourceTest.java000066400000000000000000000047361417331271500345400ustar00rootroot00000000000000orson-charts-2.1.0/src/test/java/org/jfree/chart3d/renderer/category/* =========================================================== * Orson Charts : a 3D chart library for the Java(tm) platform * =========================================================== * * (C)opyright 2013-2022, by David Gilbert. All rights reserved. * * https://github.com/jfree/orson-charts * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . * * [Oracle and Java are registered trademarks of Oracle and/or its affiliates. * Other names may be trademarks of their respective owners.] * * If you do not wish to be bound by the terms of the GPL, an alternative * commercial license can be purchased. For details, please see visit the * Orson Charts home page: * * http://www.object-refinery.com/orsoncharts/index.html * */ package org.jfree.chart3d.renderer.category; import static org.junit.jupiter.api.Assertions.assertFalse; import static org.junit.jupiter.api.Assertions.assertTrue; import org.junit.jupiter.api.Test; import java.awt.Color; import org.jfree.chart3d.TestUtils; /** * Tests for the {@link StandardCategoryColorSource} class. */ public class StandardCategoryColorSourceTest { @Test public void testEquals() { StandardCategoryColorSource s1 = new StandardCategoryColorSource(); StandardCategoryColorSource s2 = new StandardCategoryColorSource(); assertTrue(s1.equals(s2)); assertFalse(s1.equals(null)); s1 = new StandardCategoryColorSource(new Color[] { Color.BLUE }); assertFalse(s1.equals(s2)); s2 = new StandardCategoryColorSource(new Color[] { Color.BLUE }); assertTrue(s1.equals(s2)); } @Test public void testSerialization() { StandardCategoryColorSource s1 = new StandardCategoryColorSource(); StandardCategoryColorSource s2 = (StandardCategoryColorSource) TestUtils.serialized(s1); assertTrue(s1.equals(s2)); } } orson-charts-2.1.0/src/test/java/org/jfree/chart3d/renderer/xyz/000077500000000000000000000000001417331271500245015ustar00rootroot00000000000000orson-charts-2.1.0/src/test/java/org/jfree/chart3d/renderer/xyz/BarXYZRendererTest.java000066400000000000000000000071621417331271500310200ustar00rootroot00000000000000/* =========================================================== * Orson Charts : a 3D chart library for the Java(tm) platform * =========================================================== * * (C)opyright 2013-2022, by David Gilbert. All rights reserved. * * https://github.com/jfree/orson-charts * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . * * [Oracle and Java are registered trademarks of Oracle and/or its affiliates. * Other names may be trademarks of their respective owners.] * * If you do not wish to be bound by the terms of the GPL, an alternative * commercial license can be purchased. For details, please see visit the * Orson Charts home page: * * http://www.object-refinery.com/orsoncharts/index.html * */ package org.jfree.chart3d.renderer.xyz; import static org.junit.jupiter.api.Assertions.assertFalse; import static org.junit.jupiter.api.Assertions.assertTrue; import java.awt.Color; import org.junit.jupiter.api.Test; import org.jfree.chart3d.TestUtils; /** * Tests for the {@link BarXYZRenderer} class. */ public class BarXYZRendererTest { /** * Some checks for the equals() method. */ @Test public void testEquals() { BarXYZRenderer r1 = new BarXYZRenderer(); BarXYZRenderer r2 = new BarXYZRenderer(); assertTrue(r1.equals(r2)); assertFalse(r1.equals(null)); r1.setBase(1.1); assertFalse(r1.equals(r2)); r2.setBase(1.1); assertTrue(r1.equals(r2)); r1.setBarXWidth(2.2); assertFalse(r1.equals(r2)); r2.setBarXWidth(2.2); assertTrue(r1.equals(r2)); r1.setBarZWidth(3.3); assertFalse(r1.equals(r2)); r2.setBarZWidth(3.3); assertTrue(r1.equals(r2)); // baseColorSource r1.setBaseColorSource(null); assertFalse(r1.equals(r2)); r2.setBaseColorSource(null); assertTrue(r1.equals(r2)); r1.setBaseColorSource(new StandardXYZColorSource(Color.CYAN)); assertFalse(r1.equals(r2)); r2.setBaseColorSource(new StandardXYZColorSource(Color.CYAN)); assertTrue(r1.equals(r2)); // topPaintSource r1.setBaseColorSource(null); assertFalse(r1.equals(r2)); r2.setBaseColorSource(null); assertTrue(r1.equals(r2)); r1.setBaseColorSource(new StandardXYZColorSource(Color.YELLOW)); assertFalse(r1.equals(r2)); r2.setBaseColorSource(new StandardXYZColorSource(Color.YELLOW)); assertTrue(r1.equals(r2)); // regular paintSource r1.setBaseColorSource(new StandardXYZColorSource(Color.RED)); assertFalse(r1.equals(r2)); r2.setBaseColorSource(new StandardXYZColorSource(Color.RED)); assertTrue(r1.equals(r2)); } /** * Some checks for serialization support. */ @Test public void testSerialization() { BarXYZRenderer r1 = new BarXYZRenderer(); BarXYZRenderer r2 = (BarXYZRenderer) TestUtils.serialized(r1); assertTrue(r1.equals(r2)); } } orson-charts-2.1.0/src/test/java/org/jfree/chart3d/renderer/xyz/ScatterXYZRendererTest.java000066400000000000000000000044441417331271500317210ustar00rootroot00000000000000/* =========================================================== * Orson Charts : a 3D chart library for the Java(tm) platform * =========================================================== * * (C)opyright 2013-2022, by David Gilbert. All rights reserved. * * https://github.com/jfree/orson-charts * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . * * [Oracle and Java are registered trademarks of Oracle and/or its affiliates. * Other names may be trademarks of their respective owners.] * * If you do not wish to be bound by the terms of the GPL, an alternative * commercial license can be purchased. For details, please see visit the * Orson Charts home page: * * http://www.object-refinery.com/orsoncharts/index.html * */ package org.jfree.chart3d.renderer.xyz; import static org.junit.jupiter.api.Assertions.assertFalse; import static org.junit.jupiter.api.Assertions.assertTrue; import org.junit.jupiter.api.Test; import org.jfree.chart3d.TestUtils; /** * Tests for the {@link ScatterXYZRenderer} class. */ public class ScatterXYZRendererTest { @Test public void testEquals() { ScatterXYZRenderer r1 = new ScatterXYZRenderer(); ScatterXYZRenderer r2 = new ScatterXYZRenderer(); assertTrue(r1.equals(r2)); assertFalse(r1.equals(null)); r1.setSize(1.0); assertFalse(r1.equals(r2)); r2.setSize(1.0); assertTrue(r1.equals(r2)); } /** * Some checks for serialization support. */ @Test public void testSerialization() { ScatterXYZRenderer r1 = new ScatterXYZRenderer(); ScatterXYZRenderer r2 = (ScatterXYZRenderer) TestUtils.serialized(r1); assertTrue(r1.equals(r2)); } } orson-charts-2.1.0/src/test/java/org/jfree/chart3d/renderer/xyz/StandardXYZColorSourceTest.java000066400000000000000000000070051417331271500325410ustar00rootroot00000000000000/* =========================================================== * Orson Charts : a 3D chart library for the Java(tm) platform * =========================================================== * * (C)opyright 2013-2022, by David Gilbert. All rights reserved. * * https://github.com/jfree/orson-charts * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . * * [Oracle and Java are registered trademarks of Oracle and/or its affiliates. * Other names may be trademarks of their respective owners.] * * If you do not wish to be bound by the terms of the GPL, an alternative * commercial license can be purchased. For details, please see visit the * Orson Charts home page: * * http://www.object-refinery.com/orsoncharts/index.html * */ package org.jfree.chart3d.renderer.xyz; import org.jfree.chart3d.TestUtils; import java.awt.Color; import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertFalse; import static org.junit.jupiter.api.Assertions.assertTrue; import static org.junit.jupiter.api.Assertions.fail; import org.junit.jupiter.api.Test; /** * Tests for the {@link DefaultXYZPaintSource} class. */ public class StandardXYZColorSourceTest { @Test public void testConstructors() { StandardXYZColorSource scs = new StandardXYZColorSource(Color.RED); assertEquals(Color.RED, scs.getColor(0, 0)); assertEquals(Color.RED, scs.getColor(1, 0)); scs = new StandardXYZColorSource(Color.RED, Color.GREEN, Color.BLUE); assertEquals(Color.RED, scs.getColor(0, 0)); assertEquals(Color.GREEN, scs.getColor(1, 0)); assertEquals(Color.BLUE, scs.getColor(2, 0)); try { scs = new StandardXYZColorSource((Color[]) null); fail("Should have thrown an exception."); } catch (IllegalArgumentException e) { // expected } try { scs = new StandardXYZColorSource(Color.RED, null); fail("Should have thrown an exception"); } catch (IllegalArgumentException e) { // expected } } /** * Some checks for the equals() method. */ @Test public void testEquals() { StandardXYZColorSource s1 = new StandardXYZColorSource(); StandardXYZColorSource s2 = new StandardXYZColorSource(); assertTrue(s1.equals(s2)); assertFalse(s1.equals(null)); s1 = new StandardXYZColorSource(Color.BLUE); assertFalse(s1.equals(s2)); s2 = new StandardXYZColorSource(Color.BLUE); assertTrue(s1.equals(s2)); } /** * Some checks for serialization support. */ @Test public void testSerialization() { StandardXYZColorSource ps1 = new StandardXYZColorSource(); StandardXYZColorSource ps2 = (StandardXYZColorSource) TestUtils.serialized(ps1); assertTrue(ps1.equals(ps2)); } } orson-charts-2.1.0/src/test/java/org/jfree/chart3d/renderer/xyz/SurfaceRendererTest.java000066400000000000000000000066001417331271500312650ustar00rootroot00000000000000/* =========================================================== * Orson Charts : a 3D chart library for the Java(tm) platform * =========================================================== * * (C)opyright 2013-2022, by David Gilbert. All rights reserved. * * https://github.com/jfree/orson-charts * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . * * [Oracle and Java are registered trademarks of Oracle and/or its affiliates. * Other names may be trademarks of their respective owners.] * * If you do not wish to be bound by the terms of the GPL, an alternative * commercial license can be purchased. For details, please see visit the * Orson Charts home page: * * http://www.object-refinery.com/orsoncharts/index.html * */ package org.jfree.chart3d.renderer.xyz; import java.awt.Color; import static org.junit.jupiter.api.Assertions.assertFalse; import static org.junit.jupiter.api.Assertions.assertTrue; import org.junit.jupiter.api.Test; import org.jfree.chart3d.TestUtils; import org.jfree.chart3d.data.function.Function3D; import org.jfree.chart3d.renderer.FixedColorScale; /** * Tests for the {@link SurfaceRenderer} class. */ public class SurfaceRendererTest { @Test public void testEquals() { Function3D f = new Function3D() { @Override public double getValue(double x, double z) { return x + z; } }; SurfaceRenderer r1 = new SurfaceRenderer(f); SurfaceRenderer r2 = new SurfaceRenderer(f); assertTrue(r1.equals(r2)); assertFalse(r1.equals(null)); r1.setXSamples(123); assertFalse(r1.equals(r2)); r2.setXSamples(123); assertTrue(r1.equals(r2)); r1.setZSamples(22); assertFalse(r1.equals(r2)); r2.setZSamples(22); assertTrue(r1.equals(r2)); r1.setColorScale(new FixedColorScale(Color.CYAN)); assertFalse(r1.equals(r2)); r2.setColorScale(new FixedColorScale(Color.CYAN)); assertTrue(r1.equals(r2)); r1.setDrawFaceOutlines(false); assertFalse(r1.equals(r2)); r2.setDrawFaceOutlines(false); assertTrue(r1.equals(r2)); } /** * Some checks for serialization support. */ @Test public void testSerialization() { SurfaceRenderer r1 = new SurfaceRenderer(new F3D()); SurfaceRenderer r2 = (SurfaceRenderer) TestUtils.serialized(r1); assertTrue(r1.equals(r2)); } static final class F3D implements Function3D { public F3D() { } @Override public double getValue(double x, double z) { return x + z; } @Override public boolean equals(Object obj) { return obj instanceof F3D; } } } orson-charts-2.1.0/src/test/java/org/jfree/chart3d/style/000077500000000000000000000000001417331271500232015ustar00rootroot00000000000000orson-charts-2.1.0/src/test/java/org/jfree/chart3d/style/StandardChartStyleTest.java000066400000000000000000000327661417331271500304650ustar00rootroot00000000000000/* =========================================================== * Orson Charts : a 3D chart library for the Java(tm) platform * =========================================================== * * (C)opyright 2013-2022, by David Gilbert. All rights reserved. * * https://github.com/jfree/orson-charts * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . * * [Oracle and Java are registered trademarks of Oracle and/or its affiliates. * Other names may be trademarks of their respective owners.] * * If you do not wish to be bound by the terms of the GPL, an alternative * commercial license can be purchased. For details, please see visit the * Orson Charts home page: * * http://www.object-refinery.com/orsoncharts/index.html * */ package org.jfree.chart3d.style; import static org.junit.jupiter.api.Assertions.assertFalse; import static org.junit.jupiter.api.Assertions.assertArrayEquals; import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertTrue; import java.awt.BasicStroke; import java.awt.Color; import java.awt.Font; import java.awt.Rectangle; import org.junit.jupiter.api.Test; import org.jfree.chart3d.TestUtils; import org.jfree.chart3d.table.StandardRectanglePainter; /** * Tests for the {@link StandardChartStyle} class. */ public class StandardChartStyleTest { @Test public void testCopyConstructor() { StandardChartStyle s1 = new StandardChartStyle(); s1.setBackgroundPainter(new StandardRectanglePainter(Color.RED)); s1.setTitleFont(new Font(Font.SERIF, Font.PLAIN, 2)); s1.setTitleColor(Color.CYAN); s1.setTitleBackgroundColor(Color.YELLOW); s1.setSubtitleFont(new Font(Font.DIALOG, Font.PLAIN, 7)); s1.setSubtitleColor(Color.MAGENTA); s1.setSubtitleBackgroundColor(Color.PINK); s1.setChartBoxColor(Color.GREEN); s1.setXAxisGridlinesVisible(!s1.getXAxisGridlinesVisible()); s1.setYAxisGridlinesVisible(!s1.getYAxisGridlinesVisible()); s1.setZAxisGridlinesVisible(!s1.getZAxisGridlinesVisible()); s1.setGridlineColor(Color.BLUE); s1.setGridlineStroke(new BasicStroke(2.0f)); s1.setSectionLabelFont(new Font(Font.MONOSPACED, Font.PLAIN, 8)); s1.setSectionLabelColor(Color.WHITE); s1.setStandardColors(new Color[] {Color.BLACK, Color.WHITE}); s1.setAxisLabelFont(new Font(Font.SERIF, Font.PLAIN, 17)); s1.setAxisLabelColor(Color.DARK_GRAY); s1.setAxisTickLabelFont(new Font(Font.SANS_SERIF, Font.PLAIN, 11)); s1.setAxisTickLabelColor(Color.ORANGE); s1.setLegendHeaderFont(new Font(Font.MONOSPACED, Font.BOLD, 9)); s1.setLegendHeaderColor(Color.CYAN); s1.setLegendHeaderBackgroundColor(Color.RED); s1.setLegendItemShape(new Rectangle(1, 2, 3, 4)); s1.setLegendItemFont(new Font(Font.SERIF, Font.BOLD, 21)); s1.setLegendItemColor(Color.GREEN); s1.setLegendItemBackgroundColor(Color.LIGHT_GRAY); s1.setLegendFooterFont(new Font(Font.MONOSPACED, Font.ITALIC, 5)); s1.setLegendFooterColor(Color.BLUE); s1.setLegendFooterBackgroundColor(Color.BLACK); s1.setMarkerLabelFont(new Font(Font.SERIF, Font.PLAIN, 4)); s1.setMarkerLabelColor(Color.PINK); s1.setMarkerLineStroke(new BasicStroke(0.123f)); s1.setMarkerLineColor(Color.WHITE); s1.setMarkerFillColor(Color.CYAN); StandardChartStyle s2 = new StandardChartStyle(s1); assertEquals(new StandardRectanglePainter(Color.RED), s2.getBackgroundPainter()); assertEquals(new Font(Font.SERIF, Font.PLAIN, 2), s2.getTitleFont()); assertEquals(Color.CYAN, s2.getTitleColor()); assertEquals(Color.YELLOW, s2.getTitleBackgroundColor()); assertEquals(new Font(Font.DIALOG, Font.PLAIN, 7), s2.getSubtitleFont()); assertEquals(Color.MAGENTA, s2.getSubtitleColor()); assertEquals(Color.PINK, s2.getSubtitleBackgroundColor()); assertEquals(Color.GREEN, s2.getChartBoxColor()); assertEquals(s1.getXAxisGridlinesVisible(), s2.getXAxisGridlinesVisible()); assertEquals(s1.getYAxisGridlinesVisible(), s2.getYAxisGridlinesVisible()); assertEquals(s1.getZAxisGridlinesVisible(), s2.getZAxisGridlinesVisible()); assertEquals(Color.BLUE, s2.getGridlineColor()); assertEquals(new BasicStroke(2.0f), s2.getGridlineStroke()); assertEquals(new Font(Font.MONOSPACED, Font.PLAIN, 8), s2.getSectionLabelFont()); assertEquals(Color.WHITE, s2.getSectionLabelColor()); assertArrayEquals(new Color[] {Color.BLACK, Color.WHITE}, s2.getStandardColors()); assertEquals(new Font(Font.SERIF, Font.PLAIN, 17), s2.getAxisLabelFont()); assertEquals(Color.DARK_GRAY, s2.getAxisLabelColor()); assertEquals(new Font(Font.SANS_SERIF, Font.PLAIN, 11), s2.getAxisTickLabelFont()); assertEquals(Color.ORANGE, s2.getAxisTickLabelColor()); assertEquals(new Font(Font.MONOSPACED, Font.BOLD, 9), s2.getLegendHeaderFont()); assertEquals(Color.CYAN, s2.getLegendHeaderColor()); assertEquals(Color.RED, s2.getLegendHeaderBackgroundColor()); assertEquals(new Rectangle(1, 2, 3, 4), s2.getLegendItemShape()); assertEquals(new Font(Font.SERIF, Font.BOLD, 21), s2.getLegendItemFont()); assertEquals(Color.GREEN, s2.getLegendItemColor()); assertEquals(Color.LIGHT_GRAY, s2.getLegendItemBackgroundColor()); assertEquals(new Font(Font.MONOSPACED, Font.ITALIC, 5), s2.getLegendFooterFont()); assertEquals(Color.BLUE, s2.getLegendFooterColor()); assertEquals(Color.BLACK, s2.getLegendFooterBackgroundColor()); assertEquals(new Font(Font.SERIF, Font.PLAIN, 4), s2.getMarkerLabelFont()); assertEquals(Color.PINK, s2.getMarkerLabelColor()); assertEquals(new BasicStroke(0.123f), s2.getMarkerLineStroke()); assertEquals(Color.WHITE, s2.getMarkerLineColor()); assertEquals(Color.CYAN, s2.getMarkerFillColor()); } @Test public void testEquals() { StandardChartStyle s1 = new StandardChartStyle(); StandardChartStyle s2 = new StandardChartStyle(); assertTrue(s1.equals(s2)); assertFalse(s1.equals(null)); // backgroundPainter s1.setBackgroundPainter(new StandardRectanglePainter(Color.RED)); assertFalse(s1.equals(s2)); s2.setBackgroundPainter(new StandardRectanglePainter(Color.RED)); assertTrue(s1.equals(s2)); // titleFont s1.setTitleFont(new Font("Dialog", Font.PLAIN, 23)); assertFalse(s1.equals(s2)); s2.setTitleFont(new Font("Dialog", Font.PLAIN, 23)); assertTrue(s1.equals(s2)); // titleColor s1.setTitleColor(Color.GREEN); assertFalse(s1.equals(s2)); s2.setTitleColor(Color.GREEN); assertTrue(s1.equals(s2)); // titleBackgroundColor s1.setTitleBackgroundColor(Color.RED); assertFalse(s1.equals(s2)); s2.setTitleBackgroundColor(Color.RED); assertTrue(s1.equals(s2)); // subtitleFont s1.setSubtitleFont(new Font("Dialog", Font.PLAIN, 27)); assertFalse(s1.equals(s2)); s2.setSubtitleFont(new Font("Dialog", Font.PLAIN, 27)); assertTrue(s1.equals(s2)); // subtitleColor s1.setSubtitleColor(Color.CYAN); assertFalse(s1.equals(s2)); s2.setSubtitleColor(Color.CYAN); assertTrue(s1.equals(s2)); // subtitleBackgroundColor s1.setSubtitleBackgroundColor(Color.YELLOW); assertFalse(s1.equals(s2)); s2.setSubtitleBackgroundColor(Color.YELLOW); assertTrue(s1.equals(s2)); // chartBoxColor s1.setChartBoxColor(Color.DARK_GRAY); assertFalse(s1.equals(s2)); s2.setChartBoxColor(Color.DARK_GRAY); assertTrue(s1.equals(s2)); // xAxisGridlinesVisible; s1.setXAxisGridlinesVisible(!s1.getXAxisGridlinesVisible()); assertFalse(s1.equals(s2)); s2.setXAxisGridlinesVisible(!s2.getXAxisGridlinesVisible()); assertTrue(s1.equals(s2)); // yAxisGridlinesVisible; s1.setYAxisGridlinesVisible(!s1.getYAxisGridlinesVisible()); assertFalse(s1.equals(s2)); s2.setYAxisGridlinesVisible(!s2.getYAxisGridlinesVisible()); assertTrue(s1.equals(s2)); // zAxisGridlinesVisible; s1.setZAxisGridlinesVisible(!s1.getZAxisGridlinesVisible()); assertFalse(s1.equals(s2)); s2.setZAxisGridlinesVisible(!s2.getZAxisGridlinesVisible()); assertTrue(s1.equals(s2)); // gridlineColor; s1.setGridlineColor(Color.MAGENTA); assertFalse(s1.equals(s2)); s2.setGridlineColor(Color.MAGENTA); assertTrue(s1.equals(s2)); // gridlineStroke; s1.setGridlineStroke(new BasicStroke(5f)); assertFalse(s1.equals(s2)); s2.setGridlineStroke(new BasicStroke(5f)); assertTrue(s1.equals(s2)); // sectionLabelFont; s1.setSectionLabelFont(new Font("Dialog", Font.ITALIC, 7)); assertFalse(s1.equals(s2)); s2.setSectionLabelFont(new Font("Dialog", Font.ITALIC, 7)); assertTrue(s1.equals(s2)); // sectionLabelColor; s1.setSectionLabelColor(Color.DARK_GRAY); assertFalse(s1.equals(s2)); s2.setSectionLabelColor(Color.DARK_GRAY); assertTrue(s1.equals(s2)); // standardColors; s1.setStandardColors(Color.RED, Color.GREEN, Color.BLUE); assertFalse(s1.equals(s2)); s2.setStandardColors(Color.RED, Color.GREEN, Color.BLUE); assertTrue(s1.equals(s2)); // axisLabelFont; s1.setAxisLabelFont(new Font("Dialog", Font.PLAIN, 18)); assertFalse(s1.equals(s2)); s2.setAxisLabelFont(new Font("Dialog", Font.PLAIN, 18)); assertTrue(s1.equals(s2)); // axisLabelColor; s1.setAxisLabelColor(Color.WHITE); assertFalse(s1.equals(s2)); s2.setAxisLabelColor(Color.WHITE); assertTrue(s1.equals(s2)); // axisTickLabelFont; s1.setAxisTickLabelFont(new Font("Dialog", Font.BOLD, 2)); assertFalse(s1.equals(s2)); s2.setAxisTickLabelFont(new Font("Dialog", Font.BOLD, 2)); assertTrue(s1.equals(s2)); // axisTickLabelColor; s1.setAxisTickLabelColor(Color.GRAY); assertFalse(s1.equals(s2)); s2.setAxisTickLabelColor(Color.GRAY); assertTrue(s1.equals(s2)); // legendHeaderFont; s1.setLegendHeaderFont(new Font("Dialog", Font.BOLD, 99)); assertFalse(s1.equals(s2)); s2.setLegendHeaderFont(new Font("Dialog", Font.BOLD, 99)); assertTrue(s1.equals(s2)); // legendItemFont; s1.setLegendItemFont(new Font("Dialog", Font.BOLD, 99)); assertFalse(s1.equals(s2)); s2.setLegendItemFont(new Font("Dialog", Font.BOLD, 99)); assertTrue(s1.equals(s2)); // legendFooterFont; s1.setLegendFooterFont(new Font("Dialog", Font.BOLD, 99)); assertFalse(s1.equals(s2)); s2.setLegendFooterFont(new Font("Dialog", Font.BOLD, 99)); assertTrue(s1.equals(s2)); // markerLabelFont s1.setMarkerLabelFont(new Font(Font.SERIF, Font.PLAIN, 8)); assertFalse(s1.equals(s2)); s2.setMarkerLabelFont(new Font(Font.SERIF, Font.PLAIN, 8)); assertTrue(s1.equals(s2)); // markerLabelColor s1.setMarkerLabelColor(Color.MAGENTA); assertFalse(s1.equals(s2)); s2.setMarkerLabelColor(Color.MAGENTA); assertTrue(s1.equals(s2)); // markerLineStroke s1.setMarkerLineStroke(new BasicStroke(0.123f)); assertFalse(s1.equals(s2)); s2.setMarkerLineStroke(new BasicStroke(0.123f)); assertTrue(s1.equals(s2)); // markerLineColor s1.setMarkerLineColor(Color.BLUE); assertFalse(s1.equals(s2)); s2.setMarkerLineColor(Color.BLUE); assertTrue(s1.equals(s2)); // markerFillColor s1.setMarkerFillColor(Color.ORANGE); assertFalse(s1.equals(s2)); s2.setMarkerFillColor(Color.ORANGE); assertTrue(s1.equals(s2)); } @Test public void testSerialization() { StandardChartStyle s1 = new StandardChartStyle(); StandardChartStyle s2 = (StandardChartStyle) TestUtils.serialized(s1); assertTrue(s1.equals(s2)); } } orson-charts-2.1.0/src/test/java/org/jfree/chart3d/table/000077500000000000000000000000001417331271500231305ustar00rootroot00000000000000orson-charts-2.1.0/src/test/java/org/jfree/chart3d/table/ElementDimensionTest.java000066400000000000000000000047111417331271500300750ustar00rootroot00000000000000/* =========================================================== * Orson Charts : a 3D chart library for the Java(tm) platform * =========================================================== * * (C)opyright 2013-2022, by David Gilbert. All rights reserved. * * https://github.com/jfree/orson-charts * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . * * [Oracle and Java are registered trademarks of Oracle and/or its affiliates. * Other names may be trademarks of their respective owners.] * * If you do not wish to be bound by the terms of the GPL, an alternative * commercial license can be purchased. For details, please see visit the * Orson Charts home page: * * http://www.object-refinery.com/orsoncharts/index.html * */ package org.jfree.chart3d.table; import static org.junit.jupiter.api.Assertions.assertFalse; import static org.junit.jupiter.api.Assertions.assertTrue; import org.junit.jupiter.api.Test; import org.jfree.chart3d.TestUtils; /** * Tests for the {@link ElementDimension} class. */ public class ElementDimensionTest { @Test public void testEquals() { ElementDimension ed1 = new ElementDimension(1.0, 2.0); ElementDimension ed2 = new ElementDimension(1.0, 2.0); assertTrue(ed1.equals(ed2)); assertFalse(ed1.equals(null)); ed1 = new ElementDimension(3.0, 2.0); assertFalse(ed1.equals(ed2)); ed2 = new ElementDimension(3.0, 2.0); assertTrue(ed1.equals(ed2)); ed1 = new ElementDimension(3.0, 4.0); assertFalse(ed1.equals(ed2)); ed2 = new ElementDimension(3.0, 4.0); assertTrue(ed1.equals(ed2)); } @Test public void testSerialization() { ElementDimension ed1 = new ElementDimension(1.0, 2.0); ElementDimension ed2 = (ElementDimension) TestUtils.serialized(ed1); assertTrue(ed1.equals(ed2)); } } orson-charts-2.1.0/src/test/java/org/jfree/chart3d/table/FlowElementTest.java000066400000000000000000000112771417331271500270640ustar00rootroot00000000000000/* =========================================================== * Orson Charts : a 3D chart library for the Java(tm) platform * =========================================================== * * (C)opyright 2013-2022, by David Gilbert. All rights reserved. * * https://github.com/jfree/orson-charts * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . * * [Oracle and Java are registered trademarks of Oracle and/or its affiliates. * Other names may be trademarks of their respective owners.] * * If you do not wish to be bound by the terms of the GPL, an alternative * commercial license can be purchased. For details, please see visit the * Orson Charts home page: * * http://www.object-refinery.com/orsoncharts/index.html * */ package org.jfree.chart3d.table; import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertFalse; import static org.junit.jupiter.api.Assertions.assertTrue; import org.junit.jupiter.api.Test; import java.awt.Color; import java.awt.Graphics2D; import java.awt.Insets; import java.awt.Rectangle; import java.awt.geom.Dimension2D; import java.awt.image.BufferedImage; import org.jfree.chart3d.TestUtils; /** * Tests for the {@link FlowElement} class. */ public class FlowElementTest { @Test public void testEquals() { FlowElement fe1 = new FlowElement(HAlign.LEFT, 11); FlowElement fe2 = new FlowElement(HAlign.LEFT, 11); assertTrue(fe1.equals(fe2)); fe1.addElement(new TextElement("ABC")); assertFalse(fe1.equals(fe2)); fe2.addElement(new TextElement("ABC")); assertTrue(fe1.equals(fe2)); fe1.setHGap(33); assertFalse(fe1.equals(fe2)); fe2.setHGap(33); assertTrue(fe1.equals(fe2)); fe1.setHorizontalAlignment(HAlign.RIGHT); assertFalse(fe1.equals(fe2)); fe2.setHorizontalAlignment(HAlign.RIGHT); assertTrue(fe1.equals(fe2)); } @Test public void testSerialization() { FlowElement fe1 = new FlowElement(); FlowElement fe2 = (FlowElement) TestUtils.serialized(fe1); assertTrue(fe1.equals(fe2)); } private static final double EPSILON = 0.00000001; @Test public void testPreferredSize1() { BufferedImage img = new BufferedImage(100, 50, BufferedImage.TYPE_INT_ARGB); Graphics2D g2 = img.createGraphics(); FlowElement fe = new FlowElement(); ShapeElement se1 = new ShapeElement(new Rectangle(10, 5), Color.BLACK); se1.setInsets(new Insets(0, 0, 0, 0)); fe.addElement(se1); Dimension2D dim = fe.preferredSize(g2, new Rectangle(100, 50)); assertEquals(14.0, dim.getWidth(), EPSILON); assertEquals(9.0, dim.getHeight(), EPSILON); // although this element looks at the width of the bounds to determine // the layout, it will still return the minimum required size as the // preferred size, even if this exceeds the bounds dim = fe.preferredSize(g2, new Rectangle(10, 5)); assertEquals(14.0, dim.getWidth(), EPSILON); assertEquals(9.0, dim.getHeight(), EPSILON); } /** * Here we check to ensure that the first item on a new line is taken * into consideration for the width even if it is the last item in the * layout (this was a bug in the 1.0 release). */ @Test public void testPreferredSize2() { BufferedImage img = new BufferedImage(100, 50, BufferedImage.TYPE_INT_ARGB); Graphics2D g2 = img.createGraphics(); FlowElement fe = new FlowElement(); ShapeElement se1 = new ShapeElement(new Rectangle(10, 5), Color.BLACK); se1.setInsets(new Insets(0, 0, 0, 0)); ShapeElement se2 = new ShapeElement(new Rectangle(20, 5), Color.BLACK); se2.setInsets(new Insets(0, 0, 0, 0)); fe.addElement(se1); fe.addElement(se2); Dimension2D dim = fe.preferredSize(g2, new Rectangle(24, 20)); assertEquals(24.0, dim.getWidth(), EPSILON); assertEquals(14.0, dim.getHeight(), EPSILON); } } orson-charts-2.1.0/src/test/java/org/jfree/chart3d/table/GradientRectanglePainterTest.java000066400000000000000000000077251417331271500315530ustar00rootroot00000000000000/* =========================================================== * Orson Charts : a 3D chart library for the Java(tm) platform * =========================================================== * * (C)opyright 2013-2022, by David Gilbert. All rights reserved. * * https://github.com/jfree/orson-charts * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . * * [Oracle and Java are registered trademarks of Oracle and/or its affiliates. * Other names may be trademarks of their respective owners.] * * If you do not wish to be bound by the terms of the GPL, an alternative * commercial license can be purchased. For details, please see visit the * Orson Charts home page: * * http://www.object-refinery.com/orsoncharts/index.html * */ package org.jfree.chart3d.table; import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertFalse; import static org.junit.jupiter.api.Assertions.assertTrue; import org.junit.jupiter.api.Test; import java.awt.Color; import org.jfree.chart3d.TestUtils; import org.jfree.chart3d.TitleAnchor; /** * Tests for the {@link GradientRectanglePainter} class. */ public class GradientRectanglePainterTest { @Test public void testEquals() { GradientRectanglePainter grp1 = new GradientRectanglePainter(Color.RED, TitleAnchor.TOP_CENTER, Color.BLUE, TitleAnchor.BOTTOM_CENTER); GradientRectanglePainter grp2 = new GradientRectanglePainter(Color.RED, TitleAnchor.TOP_CENTER, Color.BLUE, TitleAnchor.BOTTOM_CENTER); assertTrue(grp1.equals(grp2)); grp1 = new GradientRectanglePainter(Color.GRAY, TitleAnchor.TOP_CENTER, Color.BLUE, TitleAnchor.BOTTOM_CENTER); assertFalse(grp1.equals(grp2)); grp2 = new GradientRectanglePainter(Color.GRAY, TitleAnchor.TOP_CENTER, Color.BLUE, TitleAnchor.BOTTOM_CENTER); assertTrue(grp1.equals(grp2)); grp1 = new GradientRectanglePainter(Color.GRAY, TitleAnchor.TOP_LEFT, Color.BLUE, TitleAnchor.BOTTOM_CENTER); assertFalse(grp1.equals(grp2)); grp2 = new GradientRectanglePainter(Color.GRAY, TitleAnchor.TOP_LEFT, Color.BLUE, TitleAnchor.BOTTOM_CENTER); assertTrue(grp1.equals(grp2)); grp1 = new GradientRectanglePainter(Color.GRAY, TitleAnchor.TOP_LEFT, Color.YELLOW, TitleAnchor.BOTTOM_CENTER); assertFalse(grp1.equals(grp2)); grp2 = new GradientRectanglePainter(Color.GRAY, TitleAnchor.TOP_LEFT, Color.YELLOW, TitleAnchor.BOTTOM_CENTER); assertTrue(grp1.equals(grp2)); grp1 = new GradientRectanglePainter(Color.GRAY, TitleAnchor.TOP_LEFT, Color.YELLOW, TitleAnchor.BOTTOM_RIGHT); assertFalse(grp1.equals(grp2)); grp2 = new GradientRectanglePainter(Color.GRAY, TitleAnchor.TOP_LEFT, Color.YELLOW, TitleAnchor.BOTTOM_RIGHT); assertTrue(grp1.equals(grp2)); } /** * A check for serialization. */ @Test public void testSerialization() { GradientRectanglePainter grp1 = new GradientRectanglePainter(Color.RED, TitleAnchor.TOP_CENTER, Color.BLUE, TitleAnchor.BOTTOM_CENTER); GradientRectanglePainter grp2 = (GradientRectanglePainter) TestUtils.serialized(grp1); assertEquals(grp1, grp2); } } orson-charts-2.1.0/src/test/java/org/jfree/chart3d/table/GridElementTest.java000066400000000000000000000045331417331271500270370ustar00rootroot00000000000000/* =========================================================== * Orson Charts : a 3D chart library for the Java(tm) platform * =========================================================== * * (C)opyright 2013-2022, by David Gilbert. All rights reserved. * * https://github.com/jfree/orson-charts * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . * * [Oracle and Java are registered trademarks of Oracle and/or its affiliates. * Other names may be trademarks of their respective owners.] * * If you do not wish to be bound by the terms of the GPL, an alternative * commercial license can be purchased. For details, please see visit the * Orson Charts home page: * * http://www.object-refinery.com/orsoncharts/index.html * */ package org.jfree.chart3d.table; import static org.junit.jupiter.api.Assertions.assertFalse; import static org.junit.jupiter.api.Assertions.assertTrue; import org.junit.jupiter.api.Test; import org.jfree.chart3d.TestUtils; /** * Tests for the {@link GridElement} class. */ public class GridElementTest { @Test public void testEquals() { GridElement e1 = new GridElement<>(); GridElement e2 = new GridElement<>(); assertTrue(e1.equals(e2)); e1.setElement(new TextElement("A"), "R1", "C1"); assertFalse(e1.equals(e2)); e2.setElement(new TextElement("A"), "R1", "C1"); assertTrue(e1.equals(e2)); } /** * A check for serialization. */ @Test @SuppressWarnings("unchecked") public void testSerialization() { GridElement e1 = new GridElement<>(); GridElement e2 = (GridElement) TestUtils.serialized(e1); assertTrue(e1.equals(e2)); } } orson-charts-2.1.0/src/test/java/org/jfree/chart3d/table/StandardRectanglePainterTest.java000066400000000000000000000054141417331271500315470ustar00rootroot00000000000000/* =========================================================== * Orson Charts : a 3D chart library for the Java(tm) platform * =========================================================== * * (C)opyright 2013-2022, by David Gilbert. All rights reserved. * * https://github.com/jfree/orson-charts * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . * * [Oracle and Java are registered trademarks of Oracle and/or its affiliates. * Other names may be trademarks of their respective owners.] * * If you do not wish to be bound by the terms of the GPL, an alternative * commercial license can be purchased. For details, please see visit the * Orson Charts home page: * * http://www.object-refinery.com/orsoncharts/index.html * */ package org.jfree.chart3d.table; import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertFalse; import static org.junit.jupiter.api.Assertions.assertTrue; import org.junit.jupiter.api.Test; import java.awt.Color; import java.awt.GradientPaint; import org.jfree.chart3d.TestUtils; /** * Tests for the {@link StandardRectanglePainter} class. */ public class StandardRectanglePainterTest { @Test public void testEquals() { StandardRectanglePainter srp1 = new StandardRectanglePainter(Color.RED); StandardRectanglePainter srp2 = new StandardRectanglePainter(Color.RED); assertTrue(srp1.equals(srp2)); srp1 = new StandardRectanglePainter(Color.BLUE); assertFalse(srp1.equals(srp2)); srp2 = new StandardRectanglePainter(Color.BLUE); assertTrue(srp1.equals(srp2)); } /** * A check for serialization. */ @Test public void testSerialization() { StandardRectanglePainter srp1 = new StandardRectanglePainter(Color.RED); StandardRectanglePainter srp2 = (StandardRectanglePainter) TestUtils.serialized(srp1); assertEquals(srp1, srp2); srp1 = new StandardRectanglePainter(new GradientPaint(1f, 2f, Color.RED, 3f, 4f, Color.BLUE)); srp2 = (StandardRectanglePainter) TestUtils.serialized(srp1); assertEquals(srp1, srp2); } } orson-charts-2.1.0/src/test/java/org/jfree/chart3d/table/TextElementTest.java000066400000000000000000000060011417331271500270660ustar00rootroot00000000000000/* =========================================================== * Orson Charts : a 3D chart library for the Java(tm) platform * =========================================================== * * (C)opyright 2013-2022, by David Gilbert. All rights reserved. * * https://github.com/jfree/orson-charts * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . * * [Oracle and Java are registered trademarks of Oracle and/or its affiliates. * Other names may be trademarks of their respective owners.] * * If you do not wish to be bound by the terms of the GPL, an alternative * commercial license can be purchased. For details, please see visit the * Orson Charts home page: * * http://www.object-refinery.com/orsoncharts/index.html * */ package org.jfree.chart3d.table; import static org.junit.jupiter.api.Assertions.assertFalse; import static org.junit.jupiter.api.Assertions.assertTrue; import java.awt.Color; import java.awt.Font; import java.awt.Insets; import org.junit.jupiter.api.Test; import org.jfree.chart3d.TestUtils; /** * Tests for the {@link TextElement} class. */ public class TextElementTest { @Test public void testEquals() { TextElement t1 = new TextElement("A"); TextElement t2 = new TextElement("A"); assertTrue(t1.equals(t2)); assertFalse(t1.equals(null)); // insets t1.setInsets(new Insets(1, 2, 3, 4)); assertFalse(t1.equals(t2)); t2.setInsets(new Insets(1, 2, 3, 4)); assertTrue(t1.equals(t2)); // background color t1.setBackgroundColor(Color.GREEN); assertFalse(t1.equals(t2)); t2.setBackgroundColor(Color.GREEN); assertTrue(t1.equals(t2)); // color t1.setColor(Color.MAGENTA); assertFalse(t1.equals(t2)); t2.setColor(Color.MAGENTA); assertTrue(t1.equals(t2)); t1.setFont(new Font("Dialog", Font.PLAIN, 2)); assertFalse(t1.equals(t2)); t2.setFont(new Font("Dialog", Font.PLAIN, 2)); assertTrue(t1.equals(t2)); t1.setHorizontalAligment(HAlign.RIGHT); assertFalse(t1.equals(t2)); t2.setHorizontalAligment(HAlign.RIGHT); assertTrue(t1.equals(t2)); } @Test public void testSerialization() { TextElement t1 = new TextElement("A"); TextElement t2 = (TextElement) TestUtils.serialized(t1); assertTrue(t1.equals(t2)); } } orson-charts-2.1.0/src/test/java/org/jfree/chart3d/table/VerticalFlowElementTest.java000066400000000000000000000152671417331271500305610ustar00rootroot00000000000000/* =========================================================== * Orson Charts : a 3D chart library for the Java(tm) platform * =========================================================== * * (C)opyright 2013-2022, by David Gilbert. All rights reserved. * * https://github.com/jfree/orson-charts * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . * * [Oracle and Java are registered trademarks of Oracle and/or its affiliates. * Other names may be trademarks of their respective owners.] * * If you do not wish to be bound by the terms of the GPL, an alternative * commercial license can be purchased. For details, please see visit the * Orson Charts home page: * * http://www.object-refinery.com/orsoncharts/index.html * */ package org.jfree.chart3d.table; import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertFalse; import static org.junit.jupiter.api.Assertions.assertTrue; import org.junit.jupiter.api.Test; import java.awt.Color; import java.awt.Graphics2D; import java.awt.Insets; import java.awt.Rectangle; import java.awt.geom.Dimension2D; import java.awt.image.BufferedImage; import org.jfree.chart3d.TestUtils; import java.awt.geom.Rectangle2D; import java.util.List; /** * Tests for the {@link VerticalFlowElement} class. */ public class VerticalFlowElementTest { @Test public void testEquals() { VerticalFlowElement vfe1 = new VerticalFlowElement(VAlign.TOP, 11); VerticalFlowElement vfe2 = new VerticalFlowElement(VAlign.TOP, 11); assertTrue(vfe1.equals(vfe2)); vfe1.addElement(new TextElement("ABC")); assertFalse(vfe1.equals(vfe2)); vfe2.addElement(new TextElement("ABC")); assertTrue(vfe1.equals(vfe2)); vfe1.setVGap(33); assertFalse(vfe1.equals(vfe2)); vfe2.setVGap(33); assertTrue(vfe1.equals(vfe2)); vfe1.setVerticalAlignment(VAlign.MIDDLE); assertFalse(vfe1.equals(vfe2)); vfe2.setVerticalAlignment(VAlign.MIDDLE); assertTrue(vfe1.equals(vfe2)); } @Test public void testSerialization() { VerticalFlowElement vfe1 = new VerticalFlowElement(); VerticalFlowElement vfe2 = (VerticalFlowElement) TestUtils.serialized(vfe1); assertTrue(vfe1.equals(vfe2)); } private static final double EPSILON = 0.00000001; @Test public void testPreferredSize1() { BufferedImage img = new BufferedImage(100, 50, BufferedImage.TYPE_INT_ARGB); Graphics2D g2 = img.createGraphics(); VerticalFlowElement vfe = new VerticalFlowElement(); ShapeElement se1 = new ShapeElement(new Rectangle(10, 5), Color.BLACK); se1.setInsets(new Insets(0, 0, 0, 0)); vfe.addElement(se1); Dimension2D dim = vfe.preferredSize(g2, new Rectangle(100, 50)); assertEquals(14.0, dim.getWidth(), EPSILON); assertEquals(9.0, dim.getHeight(), EPSILON); // although this element looks at the width of the bounds to determine // the layout, it will still return the minimum required size as the // preferred size, even if this exceeds the bounds dim = vfe.preferredSize(g2, new Rectangle(10, 5)); assertEquals(14.0, dim.getWidth(), EPSILON); assertEquals(9.0, dim.getHeight(), EPSILON); } /** * Here we check to ensure that the first item in a new column is taken * into consideration for the height even if it is the last item in the * layout. */ @Test public void testPreferredSize2() { BufferedImage img = new BufferedImage(100, 50, BufferedImage.TYPE_INT_ARGB); Graphics2D g2 = img.createGraphics(); VerticalFlowElement vfe = new VerticalFlowElement(); ShapeElement se1 = new ShapeElement(new Rectangle(10, 5), Color.BLACK); se1.setInsets(new Insets(0, 0, 0, 0)); ShapeElement se2 = new ShapeElement(new Rectangle(20, 10), Color.BLACK); se2.setInsets(new Insets(0, 0, 0, 0)); vfe.addElement(se1); vfe.addElement(se2); Dimension2D dim = vfe.preferredSize(g2, new Rectangle(24, 14)); assertEquals(34.0, dim.getWidth(), EPSILON); assertEquals(14.0, dim.getHeight(), EPSILON); } @Test public void testForLayoutRoundingBug() { VerticalFlowElement vfe = new VerticalFlowElement(VAlign.TOP, 2); ShapeElement s1 = new ShapeElement(new Rectangle2D.Double(0, 0, 11.25, 7.25), Color.RED); s1.setInsets(new Insets(0, 0, 0, 0)); ShapeElement s2 = new ShapeElement(new Rectangle2D.Double(0, 0, 11.25, 7.25), Color.RED); s2.setInsets(new Insets(0, 0, 0, 0)); GridElement grid1 = new GridElement<>(); grid1.setInsets(new Insets(0, 0, 0, 0)); grid1.setElement(s1, "R1", "C1"); grid1.setElement(s2, "R1", "C2"); ShapeElement s3 = new ShapeElement(new Rectangle2D.Double(0, 0, 11.25, 7.25), Color.RED); s3.setInsets(new Insets(0, 0, 0, 0)); ShapeElement s4 = new ShapeElement(new Rectangle2D.Double(0, 0, 11.25, 7.25), Color.RED); s4.setInsets(new Insets(0, 0, 0, 0)); GridElement grid2 = new GridElement<>(); grid2.setInsets(new Insets(0, 0, 0, 0)); grid2.setElement(s3, "R1", "C1"); grid2.setElement(s4, "R1", "C2"); vfe.addElement(grid1); vfe.addElement(grid2); // now test that the preferred size and the layout match BufferedImage img = new BufferedImage(100, 50, BufferedImage.TYPE_INT_ARGB); Graphics2D g2 = img.createGraphics(); Dimension2D prefSize = vfe.preferredSize(g2, new Rectangle(300, 200)); // 11.25 * 2 + insets (8 = 4 * 2) //assertEquals(30.5, prefSize.getWidth(), EPSILON); // 7.25 * 2 + vgap (2) + insets (2 + 2)? //assertEquals(20.5, prefSize.getHeight(), EPSILON); List layout = vfe.layoutElements(g2, new Rectangle2D.Double(0.0, 0.0, prefSize.getWidth(), prefSize.getHeight()), null); } } orson-charts-2.1.0/src/test/java/org/jfree/chart3d/util/000077500000000000000000000000001417331271500230165ustar00rootroot00000000000000orson-charts-2.1.0/src/test/java/org/jfree/chart3d/util/ObjectUtilsTest.java000066400000000000000000000322211417331271500267500ustar00rootroot00000000000000/* =========================================================== * Orson Charts : a 3D chart library for the Java(tm) platform * =========================================================== * * (C)opyright 2013-2022, by David Gilbert. All rights reserved. * * https://github.com/jfree/orson-charts * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . * * [Oracle and Java are registered trademarks of Oracle and/or its affiliates. * Other names may be trademarks of their respective owners.] * * If you do not wish to be bound by the terms of the GPL, an alternative * commercial license can be purchased. For details, please see visit the * Orson Charts home page: * * http://www.object-refinery.com/orsoncharts/index.html * */ package org.jfree.chart3d.util; import org.jfree.chart3d.internal.ObjectUtils; import java.awt.Color; import java.awt.GradientPaint; import java.awt.LinearGradientPaint; import java.awt.MultipleGradientPaint; import java.awt.RadialGradientPaint; import java.awt.geom.AffineTransform; import java.awt.geom.Point2D; import static org.junit.jupiter.api.Assertions.assertFalse; import static org.junit.jupiter.api.Assertions.assertTrue; import org.junit.jupiter.api.Test; /** * Some tests for the {@link ObjectUtils} class. */ public class ObjectUtilsTest { @Test public void testEquals() { assertTrue(ObjectUtils.equals(null, null)); assertFalse(ObjectUtils.equals(null, "A")); assertFalse(ObjectUtils.equals("A", null)); assertTrue(ObjectUtils.equals("A", "A")); assertFalse(ObjectUtils.equals("A", "B")); } @Test public void testEqualsPaint() { assertTrue(ObjectUtils.equalsPaint(null, null)); assertFalse(ObjectUtils.equalsPaint(null, Color.RED)); assertFalse(ObjectUtils.equals(Color.RED, null)); assertTrue(ObjectUtils.equals(Color.RED, Color.RED)); assertFalse(ObjectUtils.equals(Color.RED, Color.GREEN)); } @Test public void testEqualsPaint_GradientPaint() { GradientPaint gp1 = new GradientPaint(1.0f, 2.0f, Color.RED, 3.0f, 4.0f, Color.BLUE); GradientPaint gp2 = new GradientPaint(1.0f, 2.0f, Color.RED, 3.0f, 4.0f, Color.BLUE); assertTrue(ObjectUtils.equalsPaint(gp1, gp2)); assertTrue(ObjectUtils.equalsPaint(null, null)); assertFalse(ObjectUtils.equalsPaint(gp1, null)); assertFalse(ObjectUtils.equalsPaint(null, gp2)); gp1 = new GradientPaint(1.1f, 2.0f, Color.RED, 3.0f, 4.0f, Color.BLUE); assertFalse(ObjectUtils.equalsPaint(gp1, gp2)); gp2 = new GradientPaint(1.1f, 2.0f, Color.RED, 3.0f, 4.0f, Color.BLUE); assertTrue(ObjectUtils.equalsPaint(gp1, gp2)); gp1 = new GradientPaint(1.1f, 2.2f, Color.RED, 3.0f, 4.0f, Color.BLUE); assertFalse(ObjectUtils.equalsPaint(gp1, gp2)); gp2 = new GradientPaint(1.1f, 2.2f, Color.RED, 3.0f, 4.0f, Color.BLUE); assertTrue(ObjectUtils.equalsPaint(gp1, gp2)); gp1 = new GradientPaint(1.1f, 2.2f, Color.GRAY, 3.0f, 4.0f, Color.BLUE); assertFalse(ObjectUtils.equalsPaint(gp1, gp2)); gp2 = new GradientPaint(1.1f, 2.2f, Color.GRAY, 3.0f, 4.0f, Color.BLUE); assertTrue(ObjectUtils.equalsPaint(gp1, gp2)); gp1 = new GradientPaint(1.1f, 2.2f, Color.GRAY, 3.3f, 4.0f, Color.BLUE); assertFalse(ObjectUtils.equalsPaint(gp1, gp2)); gp2 = new GradientPaint(1.1f, 2.2f, Color.GRAY, 3.3f, 4.0f, Color.BLUE); assertTrue(ObjectUtils.equalsPaint(gp1, gp2)); gp1 = new GradientPaint(1.1f, 2.2f, Color.GRAY, 3.3f, 4.4f, Color.BLUE); assertFalse(ObjectUtils.equalsPaint(gp1, gp2)); gp2 = new GradientPaint(1.1f, 2.2f, Color.GRAY, 3.3f, 4.4f, Color.BLUE); assertTrue(ObjectUtils.equalsPaint(gp1, gp2)); gp1 = new GradientPaint(1.1f, 2.2f, Color.GRAY, 3.3f, 4.4f, Color.RED); assertFalse(ObjectUtils.equalsPaint(gp1, gp2)); gp2 = new GradientPaint(1.1f, 2.2f, Color.GRAY, 3.3f, 4.4f, Color.RED); assertTrue(ObjectUtils.equalsPaint(gp1, gp2)); } @Test public void testEqualsPaint_LinearGradientPaint() { Point2D start1 = new Point2D.Float(0, 0); Point2D end1 = new Point2D.Float(50, 50); float[] dist1 = {0.0f, 0.2f, 1.0f}; Color[] colors1 = {Color.RED, Color.WHITE, Color.BLUE}; LinearGradientPaint p1 = new LinearGradientPaint(start1, end1, dist1, colors1); Point2D start2 = new Point2D.Float(0, 0); Point2D end2 = new Point2D.Float(50, 50); float[] dist2 = {0.0f, 0.2f, 1.0f}; Color[] colors2 = {Color.RED, Color.WHITE, Color.BLUE}; LinearGradientPaint p2 = new LinearGradientPaint(start2, end2, dist2, colors2); assertTrue(ObjectUtils.equalsPaint(p1, p2)); assertFalse(ObjectUtils.equalsPaint(p1, Color.RED)); assertFalse(ObjectUtils.equalsPaint(p1, null)); assertFalse(ObjectUtils.equalsPaint(null, p1)); // check ColorSpaceType p1 = new LinearGradientPaint(start1, end1, dist1, colors1, MultipleGradientPaint.CycleMethod.NO_CYCLE, MultipleGradientPaint.ColorSpaceType.LINEAR_RGB, new AffineTransform()); p2 = new LinearGradientPaint(start1, end1, dist1, colors1, MultipleGradientPaint.CycleMethod.NO_CYCLE, MultipleGradientPaint.ColorSpaceType.SRGB, new AffineTransform()); assertFalse(ObjectUtils.equalsPaint(p1, p2)); p2 = new LinearGradientPaint(start1, end1, dist1, colors1, MultipleGradientPaint.CycleMethod.NO_CYCLE, MultipleGradientPaint.ColorSpaceType.LINEAR_RGB, new AffineTransform()); assertTrue(ObjectUtils.equalsPaint(p1, p2)); // check transform p1 = new LinearGradientPaint(start1, end1, dist1, colors1, MultipleGradientPaint.CycleMethod.NO_CYCLE, MultipleGradientPaint.ColorSpaceType.LINEAR_RGB, AffineTransform.getTranslateInstance(1.0, 2.0)); assertFalse(ObjectUtils.equalsPaint(p1, p2)); p2 = new LinearGradientPaint(start1, end1, dist1, colors1, MultipleGradientPaint.CycleMethod.NO_CYCLE, MultipleGradientPaint.ColorSpaceType.LINEAR_RGB, AffineTransform.getTranslateInstance(1.0, 2.0)); assertTrue(ObjectUtils.equalsPaint(p1, p2)); } @Test public void testEqualsPaint_RadialGradientPaint() { RadialGradientPaint p1 = new RadialGradientPaint(1.0f, 2.0f, 3.0f, new float[] {0.0f, 0.4f, 1.0f}, new Color[] {Color.RED, Color.GREEN, Color.BLUE}); RadialGradientPaint p2 = new RadialGradientPaint(1.0f, 2.0f, 3.0f, new float[] {0.0f, 0.4f, 1.0f}, new Color[] {Color.RED, Color.GREEN, Color.BLUE}); assertTrue(ObjectUtils.equalsPaint(p1, p2)); assertFalse(ObjectUtils.equalsPaint(p1, Color.RED)); assertFalse(ObjectUtils.equalsPaint(p1, null)); assertFalse(ObjectUtils.equalsPaint(null, p1)); p1 = new RadialGradientPaint(1.1f, 2.0f, 3.0f, new float[] {0.0f, 0.4f, 1.0f}, new Color[] {Color.RED, Color.GREEN, Color.BLUE}); assertFalse(ObjectUtils.equalsPaint(p1, p2)); p2 = new RadialGradientPaint(1.1f, 2.0f, 3.0f, new float[] {0.0f, 0.4f, 1.0f}, new Color[] {Color.RED, Color.GREEN, Color.BLUE}); assertTrue(ObjectUtils.equalsPaint(p1, p2)); p1 = new RadialGradientPaint(1.1f, 2.2f, 3.0f, new float[] {0.0f, 0.4f, 1.0f}, new Color[] {Color.RED, Color.GREEN, Color.BLUE}); assertFalse(ObjectUtils.equalsPaint(p1, p2)); p2 = new RadialGradientPaint(1.1f, 2.2f, 3.0f, new float[] {0.0f, 0.4f, 1.0f}, new Color[] {Color.RED, Color.GREEN, Color.BLUE}); assertTrue(ObjectUtils.equalsPaint(p1, p2)); p1 = new RadialGradientPaint(1.1f, 2.2f, 3.3f, new float[] {0.0f, 0.4f, 1.0f}, new Color[] {Color.RED, Color.GREEN, Color.BLUE}); assertFalse(ObjectUtils.equalsPaint(p1, p2)); p2 = new RadialGradientPaint(1.1f, 2.2f, 3.3f, new float[] {0.0f, 0.4f, 1.0f}, new Color[] {Color.RED, Color.GREEN, Color.BLUE}); assertTrue(ObjectUtils.equalsPaint(p1, p2)); p1 = new RadialGradientPaint(1.1f, 2.2f, 3.3f, new float[] {0.0f, 0.6f, 1.0f}, new Color[] {Color.RED, Color.GREEN, Color.BLUE}); assertFalse(ObjectUtils.equalsPaint(p1, p2)); p2 = new RadialGradientPaint(1.1f, 2.2f, 3.3f, new float[] {0.0f, 0.6f, 1.0f}, new Color[] {Color.RED, Color.GREEN, Color.BLUE}); assertTrue(ObjectUtils.equalsPaint(p1, p2)); p1 = new RadialGradientPaint(1.1f, 2.2f, 3.3f, new float[] {0.0f, 0.6f, 1.0f}, new Color[] {Color.RED, Color.YELLOW, Color.BLUE}); assertFalse(ObjectUtils.equalsPaint(p1, p2)); p2 = new RadialGradientPaint(1.1f, 2.2f, 3.3f, new float[] {0.0f, 0.6f, 1.0f}, new Color[] {Color.RED, Color.YELLOW, Color.BLUE}); assertTrue(ObjectUtils.equalsPaint(p1, p2)); p1 = new RadialGradientPaint(1.1f, 2.2f, 3.3f, new float[] {0.0f, 0.6f, 1.0f}, new Color[] {Color.RED, Color.YELLOW, Color.BLUE}, MultipleGradientPaint.CycleMethod.REPEAT); assertFalse(ObjectUtils.equalsPaint(p1, p2)); p2 = new RadialGradientPaint(1.1f, 2.2f, 3.3f, new float[] {0.0f, 0.6f, 1.0f}, new Color[] {Color.RED, Color.YELLOW, Color.BLUE}, MultipleGradientPaint.CycleMethod.REPEAT); assertTrue(ObjectUtils.equalsPaint(p1, p2)); p1 = new RadialGradientPaint(1.1f, 2.2f, 3.3f, 4.4f, 5.5f, new float[] {0.0f, 0.6f, 1.0f}, new Color[] {Color.RED, Color.YELLOW, Color.BLUE}, MultipleGradientPaint.CycleMethod.REPEAT); assertFalse(ObjectUtils.equalsPaint(p1, p2)); p2 = new RadialGradientPaint(1.1f, 2.2f, 3.3f, 4.4f, 5.5f, new float[] {0.0f, 0.6f, 1.0f}, new Color[] {Color.RED, Color.YELLOW, Color.BLUE}, MultipleGradientPaint.CycleMethod.REPEAT); assertTrue(ObjectUtils.equalsPaint(p1, p2)); // check ColorSpaceType Point2D center = new Point2D.Float(1.1f, 2.2f); float radius = 3.3f; Point2D focus = new Point2D.Float(4.4f, 5.5f); p1 = new RadialGradientPaint(center, radius, focus, new float[] {0.0f, 0.6f, 1.0f}, new Color[] {Color.RED, Color.YELLOW, Color.BLUE}, MultipleGradientPaint.CycleMethod.REPEAT, MultipleGradientPaint.ColorSpaceType.SRGB, new AffineTransform()); p2 = new RadialGradientPaint(center, radius, focus, new float[] {0.0f, 0.6f, 1.0f}, new Color[] {Color.RED, Color.YELLOW, Color.BLUE}, MultipleGradientPaint.CycleMethod.REPEAT, MultipleGradientPaint.ColorSpaceType.LINEAR_RGB, new AffineTransform()); assertFalse(ObjectUtils.equalsPaint(p1, p2)); p2 = new RadialGradientPaint(center, radius, focus, new float[] {0.0f, 0.6f, 1.0f}, new Color[] {Color.RED, Color.YELLOW, Color.BLUE}, MultipleGradientPaint.CycleMethod.REPEAT, MultipleGradientPaint.ColorSpaceType.SRGB, new AffineTransform()); assertTrue(ObjectUtils.equalsPaint(p1, p2)); // check transform p1 = new RadialGradientPaint(center, radius, focus, new float[] {0.0f, 0.6f, 1.0f}, new Color[] {Color.RED, Color.YELLOW, Color.BLUE}, MultipleGradientPaint.CycleMethod.REPEAT, MultipleGradientPaint.ColorSpaceType.SRGB, AffineTransform.getTranslateInstance(1.0, 2.0)); assertFalse(ObjectUtils.equalsPaint(p1, p2)); p2 = new RadialGradientPaint(center, radius, focus, new float[] {0.0f, 0.6f, 1.0f}, new Color[] {Color.RED, Color.YELLOW, Color.BLUE}, MultipleGradientPaint.CycleMethod.REPEAT, MultipleGradientPaint.ColorSpaceType.SRGB, AffineTransform.getTranslateInstance(1.0, 2.0)); assertTrue(ObjectUtils.equalsPaint(p1, p2)); } } orson-charts-2.1.0/svg/000077500000000000000000000000001417331271500147375ustar00rootroot00000000000000orson-charts-2.1.0/svg/SVGDemo1.html000066400000000000000000014063561417331271500171710ustar00rootroot00000000000000 SVG Demo 1

SVG Chart Demo

Click on an item in the chart or just hover and look at the tooltip (the reference is a string in JSON format that should contain enough information to identify the chart element):

Milk Products Meat Wood/Logs Crude Oil Machinery Fruit Fish Wine Other Milk Products (25%) Meat (11%) Wood/Logs (7%) Crude Oil (4%) Machinery (4%) Fruit (3%) Fish (3%) Wine (3%) Other (40%) Orson Charts (evaluation) (c) 2013, 2014, by Object Refinery LimitedNew Zealand Exports 2012 http://www.stats.govt.nz/browse_for_stats/snapshots-of-nz/nz-in-profile-2013.aspx

Q2/11 Q3/11 Q4/11 Q1/12 Q2/12 Q3/12 Q4/12 Q1/13 Q2/13 Q3/13 Q4/13 Quarter 0 20 40 60 $billion Revenues 0 20 40 60 $billion Revenues Oracle Google Microsoft Apple Oracle Google Microsoft Apple Oracle Google Microsoft Apple Orson Charts (evaluation) (c) 2013, 2014, by Object Refinery LimitedQuarterly Revenues For some large IT companies

4.5 5.0 5.5 6.0 6.5 7.0 7.5 8.0 Sepal Length 2.0 2.5 3.0 3.5 4.0 4.5 Sepal Width 1 2 3 4 5 6 7 Petal Length setosa versicolor virginica Orson Charts (evaluation) (c) 2013, 2014, by Object Refinery LimitedIris Dataset

orson-charts-2.1.0/svg/css/000077500000000000000000000000001417331271500155275ustar00rootroot00000000000000orson-charts-2.1.0/svg/css/opentip.css000066400000000000000000000213271417331271500177240ustar00rootroot00000000000000.opentip-container, .opentip-container * { -webkit-box-sizing: border-box; -moz-box-sizing: border-box; box-sizing: border-box; } .opentip-container { position: absolute; max-width: 300px; z-index: 100; -webkit-transition: -webkit-transform 1s ease-in-out; -moz-transition: -moz-transform 1s ease-in-out; -o-transition: -o-transform 1s ease-in-out; -ms-transition: -ms-transform 1s ease-in-out; transition: transform 1s ease-in-out; pointer-events: none; -webkit-transform: translateX(0) translateY(0); -moz-transform: translateX(0) translateY(0); -o-transform: translateX(0) translateY(0); -ms-transform: translateX(0) translateY(0); transform: translateX(0) translateY(0); } .opentip-container.ot-fixed.ot-hidden.stem-top.stem-center, .opentip-container.ot-fixed.ot-going-to-show.stem-top.stem-center, .opentip-container.ot-fixed.ot-hiding.stem-top.stem-center { -webkit-transform: translateY(-5px); -moz-transform: translateY(-5px); -o-transform: translateY(-5px); -ms-transform: translateY(-5px); transform: translateY(-5px); } .opentip-container.ot-fixed.ot-hidden.stem-top.stem-right, .opentip-container.ot-fixed.ot-going-to-show.stem-top.stem-right, .opentip-container.ot-fixed.ot-hiding.stem-top.stem-right { -webkit-transform: translateY(-5px) translateX(5px); -moz-transform: translateY(-5px) translateX(5px); -o-transform: translateY(-5px) translateX(5px); -ms-transform: translateY(-5px) translateX(5px); transform: translateY(-5px) translateX(5px); } .opentip-container.ot-fixed.ot-hidden.stem-middle.stem-right, .opentip-container.ot-fixed.ot-going-to-show.stem-middle.stem-right, .opentip-container.ot-fixed.ot-hiding.stem-middle.stem-right { -webkit-transform: translateX(5px); -moz-transform: translateX(5px); -o-transform: translateX(5px); -ms-transform: translateX(5px); transform: translateX(5px); } .opentip-container.ot-fixed.ot-hidden.stem-bottom.stem-right, .opentip-container.ot-fixed.ot-going-to-show.stem-bottom.stem-right, .opentip-container.ot-fixed.ot-hiding.stem-bottom.stem-right { -webkit-transform: translateY(5px) translateX(5px); -moz-transform: translateY(5px) translateX(5px); -o-transform: translateY(5px) translateX(5px); -ms-transform: translateY(5px) translateX(5px); transform: translateY(5px) translateX(5px); } .opentip-container.ot-fixed.ot-hidden.stem-bottom.stem-center, .opentip-container.ot-fixed.ot-going-to-show.stem-bottom.stem-center, .opentip-container.ot-fixed.ot-hiding.stem-bottom.stem-center { -webkit-transform: translateY(5px); -moz-transform: translateY(5px); -o-transform: translateY(5px); -ms-transform: translateY(5px); transform: translateY(5px); } .opentip-container.ot-fixed.ot-hidden.stem-bottom.stem-left, .opentip-container.ot-fixed.ot-going-to-show.stem-bottom.stem-left, .opentip-container.ot-fixed.ot-hiding.stem-bottom.stem-left { -webkit-transform: translateY(5px) translateX(-5px); -moz-transform: translateY(5px) translateX(-5px); -o-transform: translateY(5px) translateX(-5px); -ms-transform: translateY(5px) translateX(-5px); transform: translateY(5px) translateX(-5px); } .opentip-container.ot-fixed.ot-hidden.stem-middle.stem-left, .opentip-container.ot-fixed.ot-going-to-show.stem-middle.stem-left, .opentip-container.ot-fixed.ot-hiding.stem-middle.stem-left { -webkit-transform: translateX(-5px); -moz-transform: translateX(-5px); -o-transform: translateX(-5px); -ms-transform: translateX(-5px); transform: translateX(-5px); } .opentip-container.ot-fixed.ot-hidden.stem-top.stem-left, .opentip-container.ot-fixed.ot-going-to-show.stem-top.stem-left, .opentip-container.ot-fixed.ot-hiding.stem-top.stem-left { -webkit-transform: translateY(-5px) translateX(-5px); -moz-transform: translateY(-5px) translateX(-5px); -o-transform: translateY(-5px) translateX(-5px); -ms-transform: translateY(-5px) translateX(-5px); transform: translateY(-5px) translateX(-5px); } .opentip-container.ot-fixed .opentip { pointer-events: auto; } .opentip-container.ot-hidden { display: none; } .opentip-container .opentip { position: relative; font-size: 13px; line-height: 120%; padding: 9px 14px; color: #4f4b47; text-shadow: -1px -1px 0px rgba(255,255,255,0.2); } .opentip-container .opentip .header { margin: 0; padding: 0; } .opentip-container .opentip .ot-close { pointer-events: auto; display: block; position: absolute; top: -12px; left: 60px; color: rgba(0,0,0,0.5); background: rgba(0,0,0,0); text-decoration: none; } .opentip-container .opentip .ot-close span { display: none; } .opentip-container .opentip .ot-loading-indicator { display: none; } .opentip-container.ot-loading .ot-loading-indicator { width: 30px; height: 30px; font-size: 30px; line-height: 30px; font-weight: bold; display: block; } .opentip-container.ot-loading .ot-loading-indicator span { display: block; -webkit-animation: otloading 2s linear infinite; -moz-animation: otloading 2s linear infinite; -o-animation: otloading 2s linear infinite; -ms-animation: otloading 2s linear infinite; animation: otloading 2s linear infinite; text-align: center; } .opentip-container.style-dark .opentip, .opentip-container.style-alert .opentip { color: #f8f8f8; text-shadow: 1px 1px 0px rgba(0,0,0,0.2); } .opentip-container.style-glass .opentip { padding: 15px 25px; color: #317cc5; text-shadow: 1px 1px 8px rgba(0,94,153,0.3); } .opentip-container.ot-hide-effect-fade { -webkit-transition: -webkit-transform 0.5s ease-in-out, opacity 1s ease-in-out; -moz-transition: -moz-transform 0.5s ease-in-out, opacity 1s ease-in-out; -o-transition: -o-transform 0.5s ease-in-out, opacity 1s ease-in-out; -ms-transition: -ms-transform 0.5s ease-in-out, opacity 1s ease-in-out; transition: transform 0.5s ease-in-out, opacity 1s ease-in-out; opacity: 1; -ms-filter: none; filter: none; } .opentip-container.ot-hide-effect-fade.ot-hiding { opacity: 0; filter: alpha(opacity=0); -ms-filter: "progid:DXImageTransform.Microsoft.Alpha(Opacity=0)"; } .opentip-container.ot-show-effect-appear.ot-going-to-show, .opentip-container.ot-show-effect-appear.ot-showing { -webkit-transition: -webkit-transform 0.5s ease-in-out, opacity 1s ease-in-out; -moz-transition: -moz-transform 0.5s ease-in-out, opacity 1s ease-in-out; -o-transition: -o-transform 0.5s ease-in-out, opacity 1s ease-in-out; -ms-transition: -ms-transform 0.5s ease-in-out, opacity 1s ease-in-out; transition: transform 0.5s ease-in-out, opacity 1s ease-in-out; } .opentip-container.ot-show-effect-appear.ot-going-to-show { opacity: 0; filter: alpha(opacity=0); -ms-filter: "progid:DXImageTransform.Microsoft.Alpha(Opacity=0)"; } .opentip-container.ot-show-effect-appear.ot-showing { opacity: 1; -ms-filter: none; filter: none; } .opentip-container.ot-show-effect-appear.ot-visible { opacity: 1; -ms-filter: none; filter: none; } @-moz-keyframes otloading { 0% { -webkit-transform: rotate(0deg); -moz-transform: rotate(0deg); -o-transform: rotate(0deg); -ms-transform: rotate(0deg); transform: rotate(0deg); } 100% { -webkit-transform: rotate(360deg); -moz-transform: rotate(360deg); -o-transform: rotate(360deg); -ms-transform: rotate(360deg); transform: rotate(360deg); } } @-webkit-keyframes otloading { 0% { -webkit-transform: rotate(0deg); -moz-transform: rotate(0deg); -o-transform: rotate(0deg); -ms-transform: rotate(0deg); transform: rotate(0deg); } 100% { -webkit-transform: rotate(360deg); -moz-transform: rotate(360deg); -o-transform: rotate(360deg); -ms-transform: rotate(360deg); transform: rotate(360deg); } } @-o-keyframes otloading { 0% { -webkit-transform: rotate(0deg); -moz-transform: rotate(0deg); -o-transform: rotate(0deg); -ms-transform: rotate(0deg); transform: rotate(0deg); } 100% { -webkit-transform: rotate(360deg); -moz-transform: rotate(360deg); -o-transform: rotate(360deg); -ms-transform: rotate(360deg); transform: rotate(360deg); } } @-ms-keyframes otloading { 0% { -webkit-transform: rotate(0deg); -moz-transform: rotate(0deg); -o-transform: rotate(0deg); -ms-transform: rotate(0deg); transform: rotate(0deg); } 100% { -webkit-transform: rotate(360deg); -moz-transform: rotate(360deg); -o-transform: rotate(360deg); -ms-transform: rotate(360deg); transform: rotate(360deg); } } @keyframes otloading { 0% { -webkit-transform: rotate(0deg); -moz-transform: rotate(0deg); -o-transform: rotate(0deg); -ms-transform: rotate(0deg); transform: rotate(0deg); } 100% { -webkit-transform: rotate(360deg); -moz-transform: rotate(360deg); -o-transform: rotate(360deg); -ms-transform: rotate(360deg); transform: rotate(360deg); } } orson-charts-2.1.0/svg/lib/000077500000000000000000000000001417331271500155055ustar00rootroot00000000000000orson-charts-2.1.0/svg/lib/opentip-native.js000066400000000000000000002120541417331271500210110ustar00rootroot00000000000000// Generated by CoffeeScript 1.4.0 /* # # Opentip v2.4.6 # # More info at [www.opentip.org](http://www.opentip.org) # # Copyright (c) 2012, Matias Meno # Graphics by Tjandra Mayerhold # # 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. # */ var Opentip, firstAdapter, i, mouseMoved, mousePosition, mousePositionObservers, position, vendors, _i, _len, _ref, __slice = [].slice, __indexOf = [].indexOf || function(item) { for (var i = 0, l = this.length; i < l; i++) { if (i in this && this[i] === item) return i; } return -1; }, __hasProp = {}.hasOwnProperty; Opentip = (function() { Opentip.prototype.STICKS_OUT_TOP = 1; Opentip.prototype.STICKS_OUT_BOTTOM = 2; Opentip.prototype.STICKS_OUT_LEFT = 1; Opentip.prototype.STICKS_OUT_RIGHT = 2; Opentip.prototype["class"] = { container: "opentip-container", opentip: "opentip", header: "ot-header", content: "ot-content", loadingIndicator: "ot-loading-indicator", close: "ot-close", goingToHide: "ot-going-to-hide", hidden: "ot-hidden", hiding: "ot-hiding", goingToShow: "ot-going-to-show", showing: "ot-showing", visible: "ot-visible", loading: "ot-loading", ajaxError: "ot-ajax-error", fixed: "ot-fixed", showEffectPrefix: "ot-show-effect-", hideEffectPrefix: "ot-hide-effect-", stylePrefix: "style-" }; function Opentip(element, content, title, options) { var elementsOpentips, hideTrigger, methodToBind, optionSources, prop, styleName, _i, _j, _len, _len1, _ref, _ref1, _ref2, _tmpStyle, _this = this; this.id = ++Opentip.lastId; this.debug("Creating Opentip."); Opentip.tips.push(this); this.adapter = Opentip.adapter; elementsOpentips = this.adapter.data(element, "opentips") || []; elementsOpentips.push(this); this.adapter.data(element, "opentips", elementsOpentips); this.triggerElement = this.adapter.wrap(element); if (this.triggerElement.length > 1) { throw new Error("You can't call Opentip on multiple elements."); } if (this.triggerElement.length < 1) { throw new Error("Invalid element."); } this.loaded = false; this.loading = false; this.visible = false; this.waitingToShow = false; this.waitingToHide = false; this.currentPosition = { left: 0, top: 0 }; this.dimensions = { width: 100, height: 50 }; this.content = ""; this.redraw = true; this.currentObservers = { showing: false, visible: false, hiding: false, hidden: false }; options = this.adapter.clone(options); if (typeof content === "object") { options = content; content = title = void 0; } else if (typeof title === "object") { options = title; title = void 0; } if (title != null) { options.title = title; } if (content != null) { this.setContent(content); } if (options["extends"] == null) { if (options.style != null) { options["extends"] = options.style; } else { options["extends"] = Opentip.defaultStyle; } } optionSources = [options]; _tmpStyle = options; while (_tmpStyle["extends"]) { styleName = _tmpStyle["extends"]; _tmpStyle = Opentip.styles[styleName]; if (_tmpStyle == null) { throw new Error("Invalid style: " + styleName); } optionSources.unshift(_tmpStyle); if (!((_tmpStyle["extends"] != null) || styleName === "standard")) { _tmpStyle["extends"] = "standard"; } } options = (_ref = this.adapter).extend.apply(_ref, [{}].concat(__slice.call(optionSources))); options.hideTriggers = (function() { var _i, _len, _ref1, _results; _ref1 = options.hideTriggers; _results = []; for (_i = 0, _len = _ref1.length; _i < _len; _i++) { hideTrigger = _ref1[_i]; _results.push(hideTrigger); } return _results; })(); if (options.hideTrigger && options.hideTriggers.length === 0) { options.hideTriggers.push(options.hideTrigger); } _ref1 = ["tipJoint", "targetJoint", "stem"]; for (_i = 0, _len = _ref1.length; _i < _len; _i++) { prop = _ref1[_i]; if (options[prop] && typeof options[prop] === "string") { options[prop] = new Opentip.Joint(options[prop]); } } if (options.ajax && (options.ajax === true || !options.ajax)) { if (this.adapter.tagName(this.triggerElement) === "A") { options.ajax = this.adapter.attr(this.triggerElement, "href"); } else { options.ajax = false; } } if (options.showOn === "click" && this.adapter.tagName(this.triggerElement) === "A") { this.adapter.observe(this.triggerElement, "click", function(e) { e.preventDefault(); e.stopPropagation(); return e.stopped = true; }); } if (options.target) { options.fixed = true; } if (options.stem === true) { options.stem = new Opentip.Joint(options.tipJoint); } if (options.target === true) { options.target = this.triggerElement; } else if (options.target) { options.target = this.adapter.wrap(options.target); } this.currentStem = options.stem; if (options.delay == null) { options.delay = options.showOn === "mouseover" ? 0.2 : 0; } if (options.targetJoint == null) { options.targetJoint = new Opentip.Joint(options.tipJoint).flip(); } this.showTriggers = []; this.showTriggersWhenVisible = []; this.hideTriggers = []; if (options.showOn && options.showOn !== "creation") { this.showTriggers.push({ element: this.triggerElement, event: options.showOn }); } if (options.ajaxCache != null) { options.cache = options.ajaxCache; delete options.ajaxCache; } this.options = options; this.bound = {}; _ref2 = ["prepareToShow", "prepareToHide", "show", "hide", "reposition"]; for (_j = 0, _len1 = _ref2.length; _j < _len1; _j++) { methodToBind = _ref2[_j]; this.bound[methodToBind] = (function(methodToBind) { return function() { return _this[methodToBind].apply(_this, arguments); }; })(methodToBind); } this.adapter.domReady(function() { _this.activate(); if (_this.options.showOn === "creation") { return _this.prepareToShow(); } }); } Opentip.prototype._setup = function() { var hideOn, hideTrigger, hideTriggerElement, i, _i, _j, _len, _len1, _ref, _ref1, _results; this.debug("Setting up the tooltip."); this._buildContainer(); this.hideTriggers = []; _ref = this.options.hideTriggers; for (i = _i = 0, _len = _ref.length; _i < _len; i = ++_i) { hideTrigger = _ref[i]; hideTriggerElement = null; hideOn = this.options.hideOn instanceof Array ? this.options.hideOn[i] : this.options.hideOn; if (typeof hideTrigger === "string") { switch (hideTrigger) { case "trigger": hideOn = hideOn || "mouseout"; hideTriggerElement = this.triggerElement; break; case "tip": hideOn = hideOn || "mouseover"; hideTriggerElement = this.container; break; case "target": hideOn = hideOn || "mouseover"; hideTriggerElement = this.options.target; break; case "closeButton": break; default: throw new Error("Unknown hide trigger: " + hideTrigger + "."); } } else { hideOn = hideOn || "mouseover"; hideTriggerElement = this.adapter.wrap(hideTrigger); } if (hideTriggerElement) { this.hideTriggers.push({ element: hideTriggerElement, event: hideOn, original: hideTrigger }); } } _ref1 = this.hideTriggers; _results = []; for (_j = 0, _len1 = _ref1.length; _j < _len1; _j++) { hideTrigger = _ref1[_j]; _results.push(this.showTriggersWhenVisible.push({ element: hideTrigger.element, event: "mouseover" })); } return _results; }; Opentip.prototype._buildContainer = function() { this.container = this.adapter.create("
"); this.adapter.css(this.container, { position: "absolute" }); if (this.options.ajax) { this.adapter.addClass(this.container, this["class"].loading); } if (this.options.fixed) { this.adapter.addClass(this.container, this["class"].fixed); } if (this.options.showEffect) { this.adapter.addClass(this.container, "" + this["class"].showEffectPrefix + this.options.showEffect); } if (this.options.hideEffect) { return this.adapter.addClass(this.container, "" + this["class"].hideEffectPrefix + this.options.hideEffect); } }; Opentip.prototype._buildElements = function() { var headerElement, titleElement; this.tooltipElement = this.adapter.create("
"); this.backgroundCanvas = this.adapter.wrap(document.createElement("canvas")); this.adapter.css(this.backgroundCanvas, { position: "absolute" }); if (typeof G_vmlCanvasManager !== "undefined" && G_vmlCanvasManager !== null) { G_vmlCanvasManager.initElement(this.adapter.unwrap(this.backgroundCanvas)); } headerElement = this.adapter.find(this.tooltipElement, "." + this["class"].header); if (this.options.title) { titleElement = this.adapter.create("

"); this.adapter.update(titleElement, this.options.title, this.options.escapeTitle); this.adapter.append(headerElement, titleElement); } if (this.options.ajax && !this.loaded) { this.adapter.append(this.tooltipElement, this.adapter.create("
↻
")); } if (__indexOf.call(this.options.hideTriggers, "closeButton") >= 0) { this.closeButtonElement = this.adapter.create("Close"); this.adapter.append(headerElement, this.closeButtonElement); } this.adapter.append(this.container, this.backgroundCanvas); this.adapter.append(this.container, this.tooltipElement); this.adapter.append(document.body, this.container); this._newContent = true; return this.redraw = true; }; Opentip.prototype.setContent = function(content) { this.content = content; this._newContent = true; if (typeof this.content === "function") { this._contentFunction = this.content; this.content = ""; } else { this._contentFunction = null; } if (this.visible) { return this._updateElementContent(); } }; Opentip.prototype._updateElementContent = function() { var contentDiv; if (this._newContent || (!this.options.cache && this._contentFunction)) { contentDiv = this.adapter.find(this.container, "." + this["class"].content); if (contentDiv != null) { if (this._contentFunction) { this.debug("Executing content function."); this.content = this._contentFunction(this); } this.adapter.update(contentDiv, this.content, this.options.escapeContent); } this._newContent = false; } this._storeAndLockDimensions(); return this.reposition(); }; Opentip.prototype._storeAndLockDimensions = function() { var prevDimension; if (!this.container) { return; } prevDimension = this.dimensions; this.adapter.css(this.container, { width: "auto", left: "0px", top: "0px" }); this.dimensions = this.adapter.dimensions(this.container); this.dimensions.width += 1; this.adapter.css(this.container, { width: "" + this.dimensions.width + "px", top: "" + this.currentPosition.top + "px", left: "" + this.currentPosition.left + "px" }); if (!this._dimensionsEqual(this.dimensions, prevDimension)) { this.redraw = true; return this._draw(); } }; Opentip.prototype.activate = function() { return this._setupObservers("hidden", "hiding"); }; Opentip.prototype.deactivate = function() { this.debug("Deactivating tooltip."); this.hide(); return this._setupObservers("-showing", "-visible", "-hidden", "-hiding"); }; Opentip.prototype._setupObservers = function() { var observeOrStop, removeObserver, state, states, trigger, _i, _j, _k, _l, _len, _len1, _len2, _len3, _ref, _ref1, _ref2, _this = this; states = 1 <= arguments.length ? __slice.call(arguments, 0) : []; for (_i = 0, _len = states.length; _i < _len; _i++) { state = states[_i]; removeObserver = false; if (state.charAt(0) === "-") { removeObserver = true; state = state.substr(1); } if (this.currentObservers[state] === !removeObserver) { continue; } this.currentObservers[state] = !removeObserver; observeOrStop = function() { var args, _ref, _ref1; args = 1 <= arguments.length ? __slice.call(arguments, 0) : []; if (removeObserver) { return (_ref = _this.adapter).stopObserving.apply(_ref, args); } else { return (_ref1 = _this.adapter).observe.apply(_ref1, args); } }; switch (state) { case "showing": _ref = this.hideTriggers; for (_j = 0, _len1 = _ref.length; _j < _len1; _j++) { trigger = _ref[_j]; observeOrStop(trigger.element, trigger.event, this.bound.prepareToHide); } observeOrStop((document.onresize != null ? document : window), "resize", this.bound.reposition); observeOrStop(window, "scroll", this.bound.reposition); break; case "visible": _ref1 = this.showTriggersWhenVisible; for (_k = 0, _len2 = _ref1.length; _k < _len2; _k++) { trigger = _ref1[_k]; observeOrStop(trigger.element, trigger.event, this.bound.prepareToShow); } break; case "hiding": _ref2 = this.showTriggers; for (_l = 0, _len3 = _ref2.length; _l < _len3; _l++) { trigger = _ref2[_l]; observeOrStop(trigger.element, trigger.event, this.bound.prepareToShow); } break; case "hidden": break; default: throw new Error("Unknown state: " + state); } } return null; }; Opentip.prototype.prepareToShow = function() { this._abortHiding(); this._abortShowing(); if (this.visible) { return; } this.debug("Showing in " + this.options.delay + "s."); if (this.container == null) { this._setup(); } if (this.options.group) { Opentip._abortShowingGroup(this.options.group, this); } this.preparingToShow = true; this._setupObservers("-hidden", "-hiding", "showing"); this._followMousePosition(); if (this.options.fixed && !this.options.target) { this.initialMousePosition = mousePosition; } this.reposition(); return this._showTimeoutId = this.setTimeout(this.bound.show, this.options.delay || 0); }; Opentip.prototype.show = function() { var _this = this; this._abortHiding(); if (this.visible) { return; } this._clearTimeouts(); if (!this._triggerElementExists()) { return this.deactivate(); } this.debug("Showing now."); if (this.container == null) { this._setup(); } if (this.options.group) { Opentip._hideGroup(this.options.group, this); } this.visible = true; this.preparingToShow = false; if (this.tooltipElement == null) { this._buildElements(); } this._updateElementContent(); if (this.options.ajax && (!this.loaded || !this.options.cache)) { this._loadAjax(); } this._searchAndActivateCloseButtons(); this._startEnsureTriggerElement(); this.adapter.css(this.container, { zIndex: Opentip.lastZIndex++ }); this._setupObservers("-hidden", "-hiding", "-showing", "-visible", "showing", "visible"); if (this.options.fixed && !this.options.target) { this.initialMousePosition = mousePosition; } this.reposition(); this.adapter.removeClass(this.container, this["class"].hiding); this.adapter.removeClass(this.container, this["class"].hidden); this.adapter.addClass(this.container, this["class"].goingToShow); this.setCss3Style(this.container, { transitionDuration: "0s" }); this.defer(function() { var delay; if (!_this.visible || _this.preparingToHide) { return; } _this.adapter.removeClass(_this.container, _this["class"].goingToShow); _this.adapter.addClass(_this.container, _this["class"].showing); delay = 0; if (_this.options.showEffect && _this.options.showEffectDuration) { delay = _this.options.showEffectDuration; } _this.setCss3Style(_this.container, { transitionDuration: "" + delay + "s" }); _this._visibilityStateTimeoutId = _this.setTimeout(function() { _this.adapter.removeClass(_this.container, _this["class"].showing); return _this.adapter.addClass(_this.container, _this["class"].visible); }, delay); return _this._activateFirstInput(); }); return this._draw(); }; Opentip.prototype._abortShowing = function() { if (this.preparingToShow) { this.debug("Aborting showing."); this._clearTimeouts(); this._stopFollowingMousePosition(); this.preparingToShow = false; return this._setupObservers("-showing", "-visible", "hiding", "hidden"); } }; Opentip.prototype.prepareToHide = function() { this._abortShowing(); this._abortHiding(); if (!this.visible) { return; } this.debug("Hiding in " + this.options.hideDelay + "s"); this.preparingToHide = true; this._setupObservers("-showing", "visible", "-hidden", "hiding"); return this._hideTimeoutId = this.setTimeout(this.bound.hide, this.options.hideDelay); }; Opentip.prototype.hide = function() { var _this = this; this._abortShowing(); if (!this.visible) { return; } this._clearTimeouts(); this.debug("Hiding!"); this.visible = false; this.preparingToHide = false; this._stopEnsureTriggerElement(); this._setupObservers("-showing", "-visible", "-hiding", "-hidden", "hiding", "hidden"); if (!this.options.fixed) { this._stopFollowingMousePosition(); } if (!this.container) { return; } this.adapter.removeClass(this.container, this["class"].visible); this.adapter.removeClass(this.container, this["class"].showing); this.adapter.addClass(this.container, this["class"].goingToHide); this.setCss3Style(this.container, { transitionDuration: "0s" }); return this.defer(function() { var hideDelay; _this.adapter.removeClass(_this.container, _this["class"].goingToHide); _this.adapter.addClass(_this.container, _this["class"].hiding); hideDelay = 0; if (_this.options.hideEffect && _this.options.hideEffectDuration) { hideDelay = _this.options.hideEffectDuration; } _this.setCss3Style(_this.container, { transitionDuration: "" + hideDelay + "s" }); return _this._visibilityStateTimeoutId = _this.setTimeout(function() { _this.adapter.removeClass(_this.container, _this["class"].hiding); _this.adapter.addClass(_this.container, _this["class"].hidden); _this.setCss3Style(_this.container, { transitionDuration: "0s" }); if (_this.options.removeElementsOnHide) { _this.debug("Removing HTML elements."); _this.adapter.remove(_this.container); delete _this.container; return delete _this.tooltipElement; } }, hideDelay); }); }; Opentip.prototype._abortHiding = function() { if (this.preparingToHide) { this.debug("Aborting hiding."); this._clearTimeouts(); this.preparingToHide = false; return this._setupObservers("-hiding", "showing", "visible"); } }; Opentip.prototype.reposition = function() { var position, stem, _ref, _this = this; position = this.getPosition(); if (position == null) { return; } stem = this.options.stem; if (this.options.containInViewport) { _ref = this._ensureViewportContainment(position), position = _ref.position, stem = _ref.stem; } if (this._positionsEqual(position, this.currentPosition)) { return; } if (!(!this.options.stem || stem.eql(this.currentStem))) { this.redraw = true; } this.currentPosition = position; this.currentStem = stem; this._draw(); this.adapter.css(this.container, { left: "" + position.left + "px", top: "" + position.top + "px" }); return this.defer(function() { var rawContainer, redrawFix; rawContainer = _this.adapter.unwrap(_this.container); rawContainer.style.visibility = "hidden"; redrawFix = rawContainer.offsetHeight; return rawContainer.style.visibility = "visible"; }); }; Opentip.prototype.getPosition = function(tipJoint, targetJoint, stem) { var additionalHorizontal, additionalVertical, offsetDistance, position, stemLength, targetDimensions, targetPosition, unwrappedTarget, _ref; if (!this.container) { return; } if (tipJoint == null) { tipJoint = this.options.tipJoint; } if (targetJoint == null) { targetJoint = this.options.targetJoint; } position = {}; if (this.options.target) { targetPosition = this.adapter.offset(this.options.target); targetDimensions = this.adapter.dimensions(this.options.target); position = targetPosition; if (targetJoint.right) { unwrappedTarget = this.adapter.unwrap(this.options.target); if (unwrappedTarget.getBoundingClientRect != null) { position.left = unwrappedTarget.getBoundingClientRect().right + ((_ref = window.pageXOffset) != null ? _ref : document.body.scrollLeft); } else { position.left += targetDimensions.width; } } else if (targetJoint.center) { position.left += Math.round(targetDimensions.width / 2); } if (targetJoint.bottom) { position.top += targetDimensions.height; } else if (targetJoint.middle) { position.top += Math.round(targetDimensions.height / 2); } if (this.options.borderWidth) { if (this.options.tipJoint.left) { position.left += this.options.borderWidth; } if (this.options.tipJoint.right) { position.left -= this.options.borderWidth; } if (this.options.tipJoint.top) { position.top += this.options.borderWidth; } else if (this.options.tipJoint.bottom) { position.top -= this.options.borderWidth; } } } else { if (this.initialMousePosition) { position = { top: this.initialMousePosition.y, left: this.initialMousePosition.x }; } else { position = { top: mousePosition.y, left: mousePosition.x }; } } if (this.options.autoOffset) { stemLength = this.options.stem ? this.options.stemLength : 0; offsetDistance = stemLength && this.options.fixed ? 2 : 10; additionalHorizontal = tipJoint.middle && !this.options.fixed ? 15 : 0; additionalVertical = tipJoint.center && !this.options.fixed ? 15 : 0; if (tipJoint.right) { position.left -= offsetDistance + additionalHorizontal; } else if (tipJoint.left) { position.left += offsetDistance + additionalHorizontal; } if (tipJoint.bottom) { position.top -= offsetDistance + additionalVertical; } else if (tipJoint.top) { position.top += offsetDistance + additionalVertical; } if (stemLength) { if (stem == null) { stem = this.options.stem; } if (stem.right) { position.left -= stemLength; } else if (stem.left) { position.left += stemLength; } if (stem.bottom) { position.top -= stemLength; } else if (stem.top) { position.top += stemLength; } } } position.left += this.options.offset[0]; position.top += this.options.offset[1]; if (tipJoint.right) { position.left -= this.dimensions.width; } else if (tipJoint.center) { position.left -= Math.round(this.dimensions.width / 2); } if (tipJoint.bottom) { position.top -= this.dimensions.height; } else if (tipJoint.middle) { position.top -= Math.round(this.dimensions.height / 2); } return position; }; Opentip.prototype._ensureViewportContainment = function(position) { var needsRepositioning, newSticksOut, originals, revertedX, revertedY, scrollOffset, stem, sticksOut, targetJoint, tipJoint, viewportDimensions, viewportPosition; stem = this.options.stem; originals = { position: position, stem: stem }; if (!(this.visible && position)) { return originals; } sticksOut = this._sticksOut(position); if (!(sticksOut[0] || sticksOut[1])) { return originals; } tipJoint = new Opentip.Joint(this.options.tipJoint); if (this.options.targetJoint) { targetJoint = new Opentip.Joint(this.options.targetJoint); } scrollOffset = this.adapter.scrollOffset(); viewportDimensions = this.adapter.viewportDimensions(); viewportPosition = [position.left - scrollOffset[0], position.top - scrollOffset[1]]; needsRepositioning = false; if (viewportDimensions.width >= this.dimensions.width) { if (sticksOut[0]) { needsRepositioning = true; switch (sticksOut[0]) { case this.STICKS_OUT_LEFT: tipJoint.setHorizontal("left"); if (this.options.targetJoint) { targetJoint.setHorizontal("right"); } break; case this.STICKS_OUT_RIGHT: tipJoint.setHorizontal("right"); if (this.options.targetJoint) { targetJoint.setHorizontal("left"); } } } } if (viewportDimensions.height >= this.dimensions.height) { if (sticksOut[1]) { needsRepositioning = true; switch (sticksOut[1]) { case this.STICKS_OUT_TOP: tipJoint.setVertical("top"); if (this.options.targetJoint) { targetJoint.setVertical("bottom"); } break; case this.STICKS_OUT_BOTTOM: tipJoint.setVertical("bottom"); if (this.options.targetJoint) { targetJoint.setVertical("top"); } } } } if (!needsRepositioning) { return originals; } if (this.options.stem) { stem = tipJoint; } position = this.getPosition(tipJoint, targetJoint, stem); newSticksOut = this._sticksOut(position); revertedX = false; revertedY = false; if (newSticksOut[0] && (newSticksOut[0] !== sticksOut[0])) { revertedX = true; tipJoint.setHorizontal(this.options.tipJoint.horizontal); if (this.options.targetJoint) { targetJoint.setHorizontal(this.options.targetJoint.horizontal); } } if (newSticksOut[1] && (newSticksOut[1] !== sticksOut[1])) { revertedY = true; tipJoint.setVertical(this.options.tipJoint.vertical); if (this.options.targetJoint) { targetJoint.setVertical(this.options.targetJoint.vertical); } } if (revertedX && revertedY) { return originals; } if (revertedX || revertedY) { if (this.options.stem) { stem = tipJoint; } position = this.getPosition(tipJoint, targetJoint, stem); } return { position: position, stem: stem }; }; Opentip.prototype._sticksOut = function(position) { var positionOffset, scrollOffset, sticksOut, viewportDimensions; scrollOffset = this.adapter.scrollOffset(); viewportDimensions = this.adapter.viewportDimensions(); positionOffset = [position.left - scrollOffset[0], position.top - scrollOffset[1]]; sticksOut = [false, false]; if (positionOffset[0] < 0) { sticksOut[0] = this.STICKS_OUT_LEFT; } else if (positionOffset[0] + this.dimensions.width > viewportDimensions.width) { sticksOut[0] = this.STICKS_OUT_RIGHT; } if (positionOffset[1] < 0) { sticksOut[1] = this.STICKS_OUT_TOP; } else if (positionOffset[1] + this.dimensions.height > viewportDimensions.height) { sticksOut[1] = this.STICKS_OUT_BOTTOM; } return sticksOut; }; Opentip.prototype._draw = function() { var backgroundCanvas, bulge, canvasDimensions, canvasPosition, closeButton, closeButtonInner, closeButtonOuter, ctx, drawCorner, drawLine, hb, position, stemBase, stemLength, _i, _len, _ref, _ref1, _ref2, _this = this; if (!(this.backgroundCanvas && this.redraw)) { return; } this.debug("Drawing background."); this.redraw = false; if (this.currentStem) { _ref = ["top", "right", "bottom", "left"]; for (_i = 0, _len = _ref.length; _i < _len; _i++) { position = _ref[_i]; this.adapter.removeClass(this.container, "stem-" + position); } this.adapter.addClass(this.container, "stem-" + this.currentStem.horizontal); this.adapter.addClass(this.container, "stem-" + this.currentStem.vertical); } closeButtonInner = [0, 0]; closeButtonOuter = [0, 0]; if (__indexOf.call(this.options.hideTriggers, "closeButton") >= 0) { closeButton = new Opentip.Joint(((_ref1 = this.currentStem) != null ? _ref1.toString() : void 0) === "top right" ? "top left" : "top right"); closeButtonInner = [this.options.closeButtonRadius + this.options.closeButtonOffset[0], this.options.closeButtonRadius + this.options.closeButtonOffset[1]]; closeButtonOuter = [this.options.closeButtonRadius - this.options.closeButtonOffset[0], this.options.closeButtonRadius - this.options.closeButtonOffset[1]]; } canvasDimensions = this.adapter.clone(this.dimensions); canvasPosition = [0, 0]; if (this.options.borderWidth) { canvasDimensions.width += this.options.borderWidth * 2; canvasDimensions.height += this.options.borderWidth * 2; canvasPosition[0] -= this.options.borderWidth; canvasPosition[1] -= this.options.borderWidth; } if (this.options.shadow) { canvasDimensions.width += this.options.shadowBlur * 2; canvasDimensions.width += Math.max(0, this.options.shadowOffset[0] - this.options.shadowBlur * 2); canvasDimensions.height += this.options.shadowBlur * 2; canvasDimensions.height += Math.max(0, this.options.shadowOffset[1] - this.options.shadowBlur * 2); canvasPosition[0] -= Math.max(0, this.options.shadowBlur - this.options.shadowOffset[0]); canvasPosition[1] -= Math.max(0, this.options.shadowBlur - this.options.shadowOffset[1]); } bulge = { left: 0, right: 0, top: 0, bottom: 0 }; if (this.currentStem) { if (this.currentStem.left) { bulge.left = this.options.stemLength; } else if (this.currentStem.right) { bulge.right = this.options.stemLength; } if (this.currentStem.top) { bulge.top = this.options.stemLength; } else if (this.currentStem.bottom) { bulge.bottom = this.options.stemLength; } } if (closeButton) { if (closeButton.left) { bulge.left = Math.max(bulge.left, closeButtonOuter[0]); } else if (closeButton.right) { bulge.right = Math.max(bulge.right, closeButtonOuter[0]); } if (closeButton.top) { bulge.top = Math.max(bulge.top, closeButtonOuter[1]); } else if (closeButton.bottom) { bulge.bottom = Math.max(bulge.bottom, closeButtonOuter[1]); } } canvasDimensions.width += bulge.left + bulge.right; canvasDimensions.height += bulge.top + bulge.bottom; canvasPosition[0] -= bulge.left; canvasPosition[1] -= bulge.top; if (this.currentStem && this.options.borderWidth) { _ref2 = this._getPathStemMeasures(this.options.stemBase, this.options.stemLength, this.options.borderWidth), stemLength = _ref2.stemLength, stemBase = _ref2.stemBase; } backgroundCanvas = this.adapter.unwrap(this.backgroundCanvas); backgroundCanvas.width = canvasDimensions.width; backgroundCanvas.height = canvasDimensions.height; this.adapter.css(this.backgroundCanvas, { width: "" + backgroundCanvas.width + "px", height: "" + backgroundCanvas.height + "px", left: "" + canvasPosition[0] + "px", top: "" + canvasPosition[1] + "px" }); ctx = backgroundCanvas.getContext("2d"); ctx.setTransform(1, 0, 0, 1, 0, 0); ctx.clearRect(0, 0, backgroundCanvas.width, backgroundCanvas.height); ctx.beginPath(); ctx.fillStyle = this._getColor(ctx, this.dimensions, this.options.background, this.options.backgroundGradientHorizontal); ctx.lineJoin = "miter"; ctx.miterLimit = 500; hb = this.options.borderWidth / 2; if (this.options.borderWidth) { ctx.strokeStyle = this.options.borderColor; ctx.lineWidth = this.options.borderWidth; } else { stemLength = this.options.stemLength; stemBase = this.options.stemBase; } if (stemBase == null) { stemBase = 0; } drawLine = function(length, stem, first) { if (first) { ctx.moveTo(Math.max(stemBase, _this.options.borderRadius, closeButtonInner[0]) + 1 - hb, -hb); } if (stem) { ctx.lineTo(length / 2 - stemBase / 2, -hb); ctx.lineTo(length / 2, -stemLength - hb); return ctx.lineTo(length / 2 + stemBase / 2, -hb); } }; drawCorner = function(stem, closeButton, i) { var angle1, angle2, innerWidth, offset; if (stem) { ctx.lineTo(-stemBase + hb, 0 - hb); ctx.lineTo(stemLength + hb, -stemLength - hb); return ctx.lineTo(hb, stemBase - hb); } else if (closeButton) { offset = _this.options.closeButtonOffset; innerWidth = closeButtonInner[0]; if (i % 2 !== 0) { offset = [offset[1], offset[0]]; innerWidth = closeButtonInner[1]; } angle1 = Math.acos(offset[1] / _this.options.closeButtonRadius); angle2 = Math.acos(offset[0] / _this.options.closeButtonRadius); ctx.lineTo(-innerWidth + hb, -hb); return ctx.arc(hb - offset[0], -hb + offset[1], _this.options.closeButtonRadius, -(Math.PI / 2 + angle1), angle2, false); } else { ctx.lineTo(-_this.options.borderRadius + hb, -hb); return ctx.quadraticCurveTo(hb, -hb, hb, _this.options.borderRadius - hb); } }; ctx.translate(-canvasPosition[0], -canvasPosition[1]); ctx.save(); (function() { var cornerStem, i, lineLength, lineStem, positionIdx, positionX, positionY, rotation, _j, _ref3, _results; _results = []; for (i = _j = 0, _ref3 = Opentip.positions.length / 2; 0 <= _ref3 ? _j < _ref3 : _j > _ref3; i = 0 <= _ref3 ? ++_j : --_j) { positionIdx = i * 2; positionX = i === 0 || i === 3 ? 0 : _this.dimensions.width; positionY = i < 2 ? 0 : _this.dimensions.height; rotation = (Math.PI / 2) * i; lineLength = i % 2 === 0 ? _this.dimensions.width : _this.dimensions.height; lineStem = new Opentip.Joint(Opentip.positions[positionIdx]); cornerStem = new Opentip.Joint(Opentip.positions[positionIdx + 1]); ctx.save(); ctx.translate(positionX, positionY); ctx.rotate(rotation); drawLine(lineLength, lineStem.eql(_this.currentStem), i === 0); ctx.translate(lineLength, 0); drawCorner(cornerStem.eql(_this.currentStem), cornerStem.eql(closeButton), i); _results.push(ctx.restore()); } return _results; })(); ctx.closePath(); ctx.save(); if (this.options.shadow) { ctx.shadowColor = this.options.shadowColor; ctx.shadowBlur = this.options.shadowBlur; ctx.shadowOffsetX = this.options.shadowOffset[0]; ctx.shadowOffsetY = this.options.shadowOffset[1]; } ctx.fill(); ctx.restore(); if (this.options.borderWidth) { ctx.stroke(); } ctx.restore(); if (closeButton) { return (function() { var crossCenter, crossHeight, crossWidth, hcs, linkCenter; crossWidth = crossHeight = _this.options.closeButtonRadius * 2; if (closeButton.toString() === "top right") { linkCenter = [_this.dimensions.width - _this.options.closeButtonOffset[0], _this.options.closeButtonOffset[1]]; crossCenter = [linkCenter[0] + hb, linkCenter[1] - hb]; } else { linkCenter = [_this.options.closeButtonOffset[0], _this.options.closeButtonOffset[1]]; crossCenter = [linkCenter[0] - hb, linkCenter[1] - hb]; } ctx.translate(crossCenter[0], crossCenter[1]); hcs = _this.options.closeButtonCrossSize / 2; ctx.save(); ctx.beginPath(); ctx.strokeStyle = _this.options.closeButtonCrossColor; ctx.lineWidth = _this.options.closeButtonCrossLineWidth; ctx.lineCap = "round"; ctx.moveTo(-hcs, -hcs); ctx.lineTo(hcs, hcs); ctx.stroke(); ctx.beginPath(); ctx.moveTo(hcs, -hcs); ctx.lineTo(-hcs, hcs); ctx.stroke(); ctx.restore(); return _this.adapter.css(_this.closeButtonElement, { left: "" + (linkCenter[0] - hcs - _this.options.closeButtonLinkOverscan) + "px", top: "" + (linkCenter[1] - hcs - _this.options.closeButtonLinkOverscan) + "px", width: "" + (_this.options.closeButtonCrossSize + _this.options.closeButtonLinkOverscan * 2) + "px", height: "" + (_this.options.closeButtonCrossSize + _this.options.closeButtonLinkOverscan * 2) + "px" }); })(); } }; Opentip.prototype._getPathStemMeasures = function(outerStemBase, outerStemLength, borderWidth) { var angle, distanceBetweenTips, halfAngle, hb, rhombusSide, stemBase, stemLength; hb = borderWidth / 2; halfAngle = Math.atan((outerStemBase / 2) / outerStemLength); angle = halfAngle * 2; rhombusSide = hb / Math.sin(angle); distanceBetweenTips = 2 * rhombusSide * Math.cos(halfAngle); stemLength = hb + outerStemLength - distanceBetweenTips; if (stemLength < 0) { throw new Error("Sorry but your stemLength / stemBase ratio is strange."); } stemBase = (Math.tan(halfAngle) * stemLength) * 2; return { stemLength: stemLength, stemBase: stemBase }; }; Opentip.prototype._getColor = function(ctx, dimensions, color, horizontal) { var colorStop, gradient, i, _i, _len; if (horizontal == null) { horizontal = false; } if (typeof color === "string") { return color; } if (horizontal) { gradient = ctx.createLinearGradient(0, 0, dimensions.width, 0); } else { gradient = ctx.createLinearGradient(0, 0, 0, dimensions.height); } for (i = _i = 0, _len = color.length; _i < _len; i = ++_i) { colorStop = color[i]; gradient.addColorStop(colorStop[0], colorStop[1]); } return gradient; }; Opentip.prototype._searchAndActivateCloseButtons = function() { var element, _i, _len, _ref; _ref = this.adapter.findAll(this.container, "." + this["class"].close); for (_i = 0, _len = _ref.length; _i < _len; _i++) { element = _ref[_i]; this.hideTriggers.push({ element: this.adapter.wrap(element), event: "click" }); } if (this.currentObservers.showing) { this._setupObservers("-showing", "showing"); } if (this.currentObservers.visible) { return this._setupObservers("-visible", "visible"); } }; Opentip.prototype._activateFirstInput = function() { var input; input = this.adapter.unwrap(this.adapter.find(this.container, "input, textarea")); return input != null ? typeof input.focus === "function" ? input.focus() : void 0 : void 0; }; Opentip.prototype._followMousePosition = function() { if (!this.options.fixed) { return Opentip._observeMousePosition(this.bound.reposition); } }; Opentip.prototype._stopFollowingMousePosition = function() { if (!this.options.fixed) { return Opentip._stopObservingMousePosition(this.bound.reposition); } }; Opentip.prototype._clearShowTimeout = function() { return clearTimeout(this._showTimeoutId); }; Opentip.prototype._clearHideTimeout = function() { return clearTimeout(this._hideTimeoutId); }; Opentip.prototype._clearTimeouts = function() { clearTimeout(this._visibilityStateTimeoutId); this._clearShowTimeout(); return this._clearHideTimeout(); }; Opentip.prototype._triggerElementExists = function() { var el; el = this.adapter.unwrap(this.triggerElement); while (el.parentNode) { if (el.parentNode.tagName === "BODY") { return true; } el = el.parentNode; } return false; }; Opentip.prototype._loadAjax = function() { var _this = this; if (this.loading) { return; } this.loaded = false; this.loading = true; this.adapter.addClass(this.container, this["class"].loading); this.setContent(""); this.debug("Loading content from " + this.options.ajax); return this.adapter.ajax({ url: this.options.ajax, method: this.options.ajaxMethod, onSuccess: function(responseText) { _this.debug("Loading successful."); _this.adapter.removeClass(_this.container, _this["class"].loading); return _this.setContent(responseText); }, onError: function(error) { var message; message = _this.options.ajaxErrorMessage; _this.debug(message, error); _this.setContent(message); return _this.adapter.addClass(_this.container, _this["class"].ajaxError); }, onComplete: function() { _this.adapter.removeClass(_this.container, _this["class"].loading); _this.loading = false; _this.loaded = true; _this._searchAndActivateCloseButtons(); _this._activateFirstInput(); return _this.reposition(); } }); }; Opentip.prototype._ensureTriggerElement = function() { if (!this._triggerElementExists()) { this.deactivate(); return this._stopEnsureTriggerElement(); } }; Opentip.prototype._ensureTriggerElementInterval = 1000; Opentip.prototype._startEnsureTriggerElement = function() { var _this = this; return this._ensureTriggerElementTimeoutId = setInterval((function() { return _this._ensureTriggerElement(); }), this._ensureTriggerElementInterval); }; Opentip.prototype._stopEnsureTriggerElement = function() { return clearInterval(this._ensureTriggerElementTimeoutId); }; return Opentip; })(); vendors = ["khtml", "ms", "o", "moz", "webkit"]; Opentip.prototype.setCss3Style = function(element, styles) { var prop, value, vendor, vendorProp, _results; element = this.adapter.unwrap(element); _results = []; for (prop in styles) { if (!__hasProp.call(styles, prop)) continue; value = styles[prop]; if (element.style[prop] != null) { _results.push(element.style[prop] = value); } else { _results.push((function() { var _i, _len, _results1; _results1 = []; for (_i = 0, _len = vendors.length; _i < _len; _i++) { vendor = vendors[_i]; vendorProp = "" + (this.ucfirst(vendor)) + (this.ucfirst(prop)); if (element.style[vendorProp] != null) { _results1.push(element.style[vendorProp] = value); } else { _results1.push(void 0); } } return _results1; }).call(this)); } } return _results; }; Opentip.prototype.defer = function(func) { return setTimeout(func, 0); }; Opentip.prototype.setTimeout = function(func, seconds) { return setTimeout(func, seconds ? seconds * 1000 : 0); }; Opentip.prototype.ucfirst = function(string) { if (string == null) { return ""; } return string.charAt(0).toUpperCase() + string.slice(1); }; Opentip.prototype.dasherize = function(string) { return string.replace(/([A-Z])/g, function(_, character) { return "-" + (character.toLowerCase()); }); }; mousePositionObservers = []; mousePosition = { x: 0, y: 0 }; mouseMoved = function(e) { var observer, _i, _len, _results; mousePosition = Opentip.adapter.mousePosition(e); _results = []; for (_i = 0, _len = mousePositionObservers.length; _i < _len; _i++) { observer = mousePositionObservers[_i]; _results.push(observer()); } return _results; }; Opentip.followMousePosition = function() { return Opentip.adapter.observe(document.body, "mousemove", mouseMoved); }; Opentip._observeMousePosition = function(observer) { return mousePositionObservers.push(observer); }; Opentip._stopObservingMousePosition = function(removeObserver) { var observer; return mousePositionObservers = (function() { var _i, _len, _results; _results = []; for (_i = 0, _len = mousePositionObservers.length; _i < _len; _i++) { observer = mousePositionObservers[_i]; if (observer !== removeObserver) { _results.push(observer); } } return _results; })(); }; Opentip.Joint = (function() { function Joint(pointerString) { if (pointerString == null) { return; } if (pointerString instanceof Opentip.Joint) { pointerString = pointerString.toString(); } this.set(pointerString); this; } Joint.prototype.set = function(string) { string = string.toLowerCase(); this.setHorizontal(string); this.setVertical(string); return this; }; Joint.prototype.setHorizontal = function(string) { var i, valid, _i, _j, _len, _len1, _results; valid = ["left", "center", "right"]; for (_i = 0, _len = valid.length; _i < _len; _i++) { i = valid[_i]; if (~string.indexOf(i)) { this.horizontal = i.toLowerCase(); } } if (this.horizontal == null) { this.horizontal = "center"; } _results = []; for (_j = 0, _len1 = valid.length; _j < _len1; _j++) { i = valid[_j]; _results.push(this[i] = this.horizontal === i ? i : void 0); } return _results; }; Joint.prototype.setVertical = function(string) { var i, valid, _i, _j, _len, _len1, _results; valid = ["top", "middle", "bottom"]; for (_i = 0, _len = valid.length; _i < _len; _i++) { i = valid[_i]; if (~string.indexOf(i)) { this.vertical = i.toLowerCase(); } } if (this.vertical == null) { this.vertical = "middle"; } _results = []; for (_j = 0, _len1 = valid.length; _j < _len1; _j++) { i = valid[_j]; _results.push(this[i] = this.vertical === i ? i : void 0); } return _results; }; Joint.prototype.eql = function(pointer) { return (pointer != null) && this.horizontal === pointer.horizontal && this.vertical === pointer.vertical; }; Joint.prototype.flip = function() { var flippedIndex, positionIdx; positionIdx = Opentip.position[this.toString(true)]; flippedIndex = (positionIdx + 4) % 8; this.set(Opentip.positions[flippedIndex]); return this; }; Joint.prototype.toString = function(camelized) { var horizontal, vertical; if (camelized == null) { camelized = false; } vertical = this.vertical === "middle" ? "" : this.vertical; horizontal = this.horizontal === "center" ? "" : this.horizontal; if (vertical && horizontal) { if (camelized) { horizontal = Opentip.prototype.ucfirst(horizontal); } else { horizontal = " " + horizontal; } } return "" + vertical + horizontal; }; return Joint; })(); Opentip.prototype._positionsEqual = function(posA, posB) { return (posA != null) && (posB != null) && posA.left === posB.left && posA.top === posB.top; }; Opentip.prototype._dimensionsEqual = function(dimA, dimB) { return (dimA != null) && (dimB != null) && dimA.width === dimB.width && dimA.height === dimB.height; }; Opentip.prototype.debug = function() { var args; args = 1 <= arguments.length ? __slice.call(arguments, 0) : []; if (Opentip.debug && ((typeof console !== "undefined" && console !== null ? console.debug : void 0) != null)) { args.unshift("#" + this.id + " |"); return console.debug.apply(console, args); } }; Opentip.findElements = function() { var adapter, content, element, optionName, optionValue, options, _i, _len, _ref, _results; adapter = Opentip.adapter; _ref = adapter.findAll(document.body, "[data-ot]"); _results = []; for (_i = 0, _len = _ref.length; _i < _len; _i++) { element = _ref[_i]; options = {}; content = adapter.data(element, "ot"); if (content === "" || content === "true" || content === "yes") { content = adapter.attr(element, "title"); adapter.attr(element, "title", ""); } content = content || ""; for (optionName in Opentip.styles.standard) { optionValue = adapter.data(element, "ot" + (Opentip.prototype.ucfirst(optionName))); if (optionValue != null) { if (optionValue === "yes" || optionValue === "true" || optionValue === "on") { optionValue = true; } else if (optionValue === "no" || optionValue === "false" || optionValue === "off") { optionValue = false; } options[optionName] = optionValue; } } _results.push(new Opentip(element, content, options)); } return _results; }; Opentip.version = "2.4.6"; Opentip.debug = false; Opentip.lastId = 0; Opentip.lastZIndex = 100; Opentip.tips = []; Opentip._abortShowingGroup = function(group, originatingOpentip) { var opentip, _i, _len, _ref, _results; _ref = Opentip.tips; _results = []; for (_i = 0, _len = _ref.length; _i < _len; _i++) { opentip = _ref[_i]; if (opentip !== originatingOpentip && opentip.options.group === group) { _results.push(opentip._abortShowing()); } else { _results.push(void 0); } } return _results; }; Opentip._hideGroup = function(group, originatingOpentip) { var opentip, _i, _len, _ref, _results; _ref = Opentip.tips; _results = []; for (_i = 0, _len = _ref.length; _i < _len; _i++) { opentip = _ref[_i]; if (opentip !== originatingOpentip && opentip.options.group === group) { _results.push(opentip.hide()); } else { _results.push(void 0); } } return _results; }; Opentip.adapters = {}; Opentip.adapter = null; firstAdapter = true; Opentip.addAdapter = function(adapter) { Opentip.adapters[adapter.name] = adapter; if (firstAdapter) { Opentip.adapter = adapter; adapter.domReady(Opentip.findElements); adapter.domReady(Opentip.followMousePosition); return firstAdapter = false; } }; Opentip.positions = ["top", "topRight", "right", "bottomRight", "bottom", "bottomLeft", "left", "topLeft"]; Opentip.position = {}; _ref = Opentip.positions; for (i = _i = 0, _len = _ref.length; _i < _len; i = ++_i) { position = _ref[i]; Opentip.position[position] = i; } Opentip.styles = { standard: { "extends": null, title: void 0, escapeTitle: true, escapeContent: false, className: "standard", stem: true, delay: null, hideDelay: 0.1, fixed: false, showOn: "mouseover", hideTrigger: "trigger", hideTriggers: [], hideOn: null, removeElementsOnHide: false, offset: [0, 0], containInViewport: true, autoOffset: true, showEffect: "appear", hideEffect: "fade", showEffectDuration: 0.3, hideEffectDuration: 0.2, stemLength: 5, stemBase: 8, tipJoint: "top left", target: null, targetJoint: null, cache: true, ajax: false, ajaxMethod: "GET", ajaxErrorMessage: "There was a problem downloading the content.", group: null, style: null, background: "#fff18f", backgroundGradientHorizontal: false, closeButtonOffset: [5, 5], closeButtonRadius: 7, closeButtonCrossSize: 4, closeButtonCrossColor: "#d2c35b", closeButtonCrossLineWidth: 1.5, closeButtonLinkOverscan: 6, borderRadius: 5, borderWidth: 1, borderColor: "#f2e37b", shadow: true, shadowBlur: 10, shadowOffset: [3, 3], shadowColor: "rgba(0, 0, 0, 0.1)" }, glass: { "extends": "standard", className: "glass", background: [[0, "rgba(252, 252, 252, 0.8)"], [0.5, "rgba(255, 255, 255, 0.8)"], [0.5, "rgba(250, 250, 250, 0.9)"], [1, "rgba(245, 245, 245, 0.9)"]], borderColor: "#eee", closeButtonCrossColor: "rgba(0, 0, 0, 0.2)", borderRadius: 15, closeButtonRadius: 10, closeButtonOffset: [8, 8] }, dark: { "extends": "standard", className: "dark", borderRadius: 13, borderColor: "#444", closeButtonCrossColor: "rgba(240, 240, 240, 1)", shadowColor: "rgba(0, 0, 0, 0.3)", shadowOffset: [2, 2], background: [[0, "rgba(30, 30, 30, 0.7)"], [0.5, "rgba(30, 30, 30, 0.8)"], [0.5, "rgba(10, 10, 10, 0.8)"], [1, "rgba(10, 10, 10, 0.9)"]] }, alert: { "extends": "standard", className: "alert", borderRadius: 1, borderColor: "#AE0D11", closeButtonCrossColor: "rgba(255, 255, 255, 1)", shadowColor: "rgba(0, 0, 0, 0.3)", shadowOffset: [2, 2], background: [[0, "rgba(203, 15, 19, 0.7)"], [0.5, "rgba(203, 15, 19, 0.8)"], [0.5, "rgba(189, 14, 18, 0.8)"], [1, "rgba(179, 14, 17, 0.9)"]] } }; Opentip.defaultStyle = "standard"; if (typeof module !== "undefined" && module !== null) { module.exports = Opentip; } else { window.Opentip = Opentip; } // Generated by CoffeeScript 1.4.0 var Adapter, __hasProp = {}.hasOwnProperty, __slice = [].slice; Adapter = (function() { var dataValues, lastDataId; function Adapter() {} Adapter.prototype.name = "native"; Adapter.prototype.domReady = function(callback) { var add, doc, done, init, poll, pre, rem, root, top, win, _ref; done = false; top = true; win = window; doc = document; if ((_ref = doc.readyState) === "complete" || _ref === "loaded") { return callback(); } root = doc.documentElement; add = (doc.addEventListener ? "addEventListener" : "attachEvent"); rem = (doc.addEventListener ? "removeEventListener" : "detachEvent"); pre = (doc.addEventListener ? "" : "on"); init = function(e) { if (e.type === "readystatechange" && doc.readyState !== "complete") { return; } (e.type === "load" ? win : doc)[rem](pre + e.type, init, false); if (!done) { done = true; return callback(); } }; poll = function() { try { root.doScroll("left"); } catch (e) { setTimeout(poll, 50); return; } return init("poll"); }; if (doc.readyState !== "complete") { if (doc.createEventObject && root.doScroll) { try { top = !win.frameElement; } catch (_error) {} if (top) { poll(); } } doc[add](pre + "DOMContentLoaded", init, false); doc[add](pre + "readystatechange", init, false); return win[add](pre + "load", init, false); } }; Adapter.prototype.create = function(htmlString) { var div; div = document.createElement("div"); div.innerHTML = htmlString; return this.wrap(div.childNodes); }; Adapter.prototype.wrap = function(element) { var el; if (!element) { element = []; } else if (typeof element === "string") { element = this.find(document.body, element); element = element ? [element] : []; } else if (element instanceof NodeList) { element = (function() { var _i, _len, _results; _results = []; for (_i = 0, _len = element.length; _i < _len; _i++) { el = element[_i]; _results.push(el); } return _results; })(); } else if (!(element instanceof Array)) { element = [element]; } return element; }; Adapter.prototype.unwrap = function(element) { return this.wrap(element)[0]; }; Adapter.prototype.tagName = function(element) { return this.unwrap(element).tagName; }; Adapter.prototype.attr = function(element, attr, value) { if (arguments.length === 3) { return this.unwrap(element).setAttribute(attr, value); } else { return this.unwrap(element).getAttribute(attr); } }; lastDataId = 0; dataValues = {}; Adapter.prototype.data = function(element, name, value) { var dataId; dataId = this.attr(element, "data-id"); if (!dataId) { dataId = ++lastDataId; this.attr(element, "data-id", dataId); dataValues[dataId] = {}; } if (arguments.length === 3) { return dataValues[dataId][name] = value; } else { value = dataValues[dataId][name]; if (value != null) { return value; } value = this.attr(element, "data-" + (Opentip.prototype.dasherize(name))); if (value) { dataValues[dataId][name] = value; } return value; } }; Adapter.prototype.find = function(element, selector) { return this.unwrap(element).querySelector(selector); }; Adapter.prototype.findAll = function(element, selector) { return this.unwrap(element).querySelectorAll(selector); }; Adapter.prototype.update = function(element, content, escape) { element = this.unwrap(element); if (escape) { element.innerHTML = ""; return element.appendChild(document.createTextNode(content)); } else { return element.innerHTML = content; } }; Adapter.prototype.append = function(element, child) { var unwrappedChild, unwrappedElement; unwrappedChild = this.unwrap(child); unwrappedElement = this.unwrap(element); return unwrappedElement.appendChild(unwrappedChild); }; Adapter.prototype.remove = function(element) { var parentNode; element = this.unwrap(element); parentNode = element.parentNode; if (parentNode != null) { return parentNode.removeChild(element); } }; Adapter.prototype.addClass = function(element, className) { return this.unwrap(element).classList.add(className); }; Adapter.prototype.removeClass = function(element, className) { return this.unwrap(element).classList.remove(className); }; Adapter.prototype.css = function(element, properties) { var key, value, _results; element = this.unwrap(this.wrap(element)); _results = []; for (key in properties) { if (!__hasProp.call(properties, key)) continue; value = properties[key]; _results.push(element.style[key] = value); } return _results; }; Adapter.prototype.dimensions = function(element) { var dimensions, revert; element = this.unwrap(this.wrap(element)); dimensions = { width: element.offsetWidth, height: element.offsetHeight }; if (!(dimensions.width && dimensions.height)) { revert = { position: element.style.position || '', visibility: element.style.visibility || '', display: element.style.display || '' }; this.css(element, { position: "absolute", visibility: "hidden", display: "block" }); dimensions = { width: element.offsetWidth, height: element.offsetHeight }; this.css(element, revert); } return dimensions; }; Adapter.prototype.scrollOffset = function() { return [window.pageXOffset || document.documentElement.scrollLeft || document.body.scrollLeft, window.pageYOffset || document.documentElement.scrollTop || document.body.scrollTop]; }; Adapter.prototype.viewportDimensions = function() { return { width: document.documentElement.clientWidth, height: document.documentElement.clientHeight }; }; Adapter.prototype.mousePosition = function(e) { var pos; pos = { x: 0, y: 0 }; if (e == null) { e = window.event; } if (e == null) { return; } try { if (e.pageX || e.pageY) { pos.x = e.pageX; pos.y = e.pageY; } else if (e.clientX || e.clientY) { pos.x = e.clientX + document.body.scrollLeft + document.documentElement.scrollLeft; pos.y = e.clientY + document.body.scrollTop + document.documentElement.scrollTop; } } catch (e) { } return pos; }; Adapter.prototype.offset = function(element) { var offset; element = this.unwrap(element); offset = { top: element.offsetTop, left: element.offsetLeft }; while (element = element.offsetParent) { offset.top += element.offsetTop; offset.left += element.offsetLeft; if (element !== document.body) { offset.top -= element.scrollTop; offset.left -= element.scrollLeft; } } return offset; }; Adapter.prototype.observe = function(element, eventName, observer) { return this.unwrap(element).addEventListener(eventName, observer, false); }; Adapter.prototype.stopObserving = function(element, eventName, observer) { return this.unwrap(element).removeEventListener(eventName, observer, false); }; Adapter.prototype.ajax = function(options) { var request, _ref, _ref1; if (options.url == null) { throw new Error("No url provided"); } if (window.XMLHttpRequest) { request = new XMLHttpRequest; } else if (window.ActiveXObject) { try { request = new ActiveXObject("Msxml2.XMLHTTP"); } catch (e) { try { request = new ActiveXObject("Microsoft.XMLHTTP"); } catch (e) { } } } if (!request) { throw new Error("Can't create XMLHttpRequest"); } request.onreadystatechange = function() { if (request.readyState === 4) { try { if (request.status === 200) { if (typeof options.onSuccess === "function") { options.onSuccess(request.responseText); } } else { if (typeof options.onError === "function") { options.onError("Server responded with status " + request.status); } } } catch (e) { if (typeof options.onError === "function") { options.onError(e.message); } } return typeof options.onComplete === "function" ? options.onComplete() : void 0; } }; request.open((_ref = (_ref1 = options.method) != null ? _ref1.toUpperCase() : void 0) != null ? _ref : "GET", options.url); return request.send(); }; Adapter.prototype.clone = function(object) { var key, newObject, val; newObject = {}; for (key in object) { if (!__hasProp.call(object, key)) continue; val = object[key]; newObject[key] = val; } return newObject; }; Adapter.prototype.extend = function() { var key, source, sources, target, val, _i, _len; target = arguments[0], sources = 2 <= arguments.length ? __slice.call(arguments, 1) : []; for (_i = 0, _len = sources.length; _i < _len; _i++) { source = sources[_i]; for (key in source) { if (!__hasProp.call(source, key)) continue; val = source[key]; target[key] = val; } } return target; }; return Adapter; })(); Opentip.addAdapter(new Adapter); /* * classList.js: Cross-browser full element.classList implementation. * 2012-11-15 * * By Eli Grey, http://eligrey.com * Public Domain. * NO WARRANTY EXPRESSED OR IMPLIED. USE AT YOUR OWN RISK. */ /*global self, document, DOMException */ /*! @source http://purl.eligrey.com/github/classList.js/blob/master/classList.js*/ if (typeof document !== "undefined" && !("classList" in document.createElement("a"))) { (function (view) { "use strict"; if (!('HTMLElement' in view) && !('Element' in view)) return; var classListProp = "classList" , protoProp = "prototype" , elemCtrProto = (view.HTMLElement || view.Element)[protoProp] , objCtr = Object , strTrim = String[protoProp].trim || function () { return this.replace(/^\s+|\s+$/g, ""); } , arrIndexOf = Array[protoProp].indexOf || function (item) { var i = 0 , len = this.length ; for (; i < len; i++) { if (i in this && this[i] === item) { return i; } } return -1; } // Vendors: please allow content code to instantiate DOMExceptions , DOMEx = function (type, message) { this.name = type; this.code = DOMException[type]; this.message = message; } , checkTokenAndGetIndex = function (classList, token) { if (token === "") { throw new DOMEx( "SYNTAX_ERR" , "An invalid or illegal string was specified" ); } if (/\s/.test(token)) { throw new DOMEx( "INVALID_CHARACTER_ERR" , "String contains an invalid character" ); } return arrIndexOf.call(classList, token); } , ClassList = function (elem) { var trimmedClasses = strTrim.call(elem.className) , classes = trimmedClasses ? trimmedClasses.split(/\s+/) : [] , i = 0 , len = classes.length ; for (; i < len; i++) { this.push(classes[i]); } this._updateClassName = function () { elem.className = this.toString(); }; } , classListProto = ClassList[protoProp] = [] , classListGetter = function () { return new ClassList(this); } ; // Most DOMException implementations don't allow calling DOMException's toString() // on non-DOMExceptions. Error's toString() is sufficient here. DOMEx[protoProp] = Error[protoProp]; classListProto.item = function (i) { return this[i] || null; }; classListProto.contains = function (token) { token += ""; return checkTokenAndGetIndex(this, token) !== -1; }; classListProto.add = function () { var tokens = arguments , i = 0 , l = tokens.length , token , updated = false ; do { token = tokens[i] + ""; if (checkTokenAndGetIndex(this, token) === -1) { this.push(token); updated = true; } } while (++i < l); if (updated) { this._updateClassName(); } }; classListProto.remove = function () { var tokens = arguments , i = 0 , l = tokens.length , token , updated = false ; do { token = tokens[i] + ""; var index = checkTokenAndGetIndex(this, token); if (index !== -1) { this.splice(index, 1); updated = true; } } while (++i < l); if (updated) { this._updateClassName(); } }; classListProto.toggle = function (token, forse) { token += ""; var result = this.contains(token) , method = result ? forse !== true && "remove" : forse !== false && "add" ; if (method) { this[method](token); } return result; }; classListProto.toString = function () { return this.join(" "); }; if (objCtr.defineProperty) { var classListPropDesc = { get: classListGetter , enumerable: true , configurable: true }; try { objCtr.defineProperty(elemCtrProto, classListProp, classListPropDesc); } catch (ex) { // IE 8 doesn't support enumerable:true if (ex.number === -0x7FF5EC54) { classListPropDesc.enumerable = false; objCtr.defineProperty(elemCtrProto, classListProp, classListPropDesc); } } } else if (objCtr[protoProp].__defineGetter__) { elemCtrProto.__defineGetter__(classListProp, classListGetter); } }(self)); } !window.addEventListener && (function (WindowPrototype, DocumentPrototype, ElementPrototype, addEventListener, removeEventListener, dispatchEvent, registry) { WindowPrototype[addEventListener] = DocumentPrototype[addEventListener] = ElementPrototype[addEventListener] = function (type, listener) { var target = this; registry.unshift([target, type, listener, function (event) { event.currentTarget = target; event.preventDefault = function () { event.returnValue = false }; event.stopPropagation = function () { event.cancelBubble = true }; event.target = event.srcElement || target; listener.call(target, event); }]); this.attachEvent("on" + type, registry[0][3]); }; WindowPrototype[removeEventListener] = DocumentPrototype[removeEventListener] = ElementPrototype[removeEventListener] = function (type, listener) { for (var index = 0, register; register = registry[index]; ++index) { if (register[0] == this && register[1] == type && register[2] == listener) { return this.detachEvent("on" + type, registry.splice(index, 1)[0][3]); } } }; WindowPrototype[dispatchEvent] = DocumentPrototype[dispatchEvent] = ElementPrototype[dispatchEvent] = function (eventObject) { return this.fireEvent("on" + eventObject.type, eventObject); }; })(Window.prototype, HTMLDocument.prototype, Element.prototype, "addEventListener", "removeEventListener", "dispatchEvent", []);orson-charts-2.1.0/svg/lib/orsoncharts.js000066400000000000000000000310151417331271500204100ustar00rootroot00000000000000var orsoncharts;if(!orsoncharts)orsoncharts={};orsoncharts.Utils={};orsoncharts.Utils.makeArrayOf=function(value,length){var arr=[],i=length;while(i--)arr[i]=value;return arr};orsoncharts.Utils.findChartRef=function(element){var id=element.getAttribute("jfreesvg:ref");var found=false;var current=element;while(!found){current=current.parentNode;if(current!=null){id=current.getAttribute("jfreesvg:ref");found=id!=null}else found=true}return id}; orsoncharts.Utils.findChartId=function(element){var id=null;var found=false;var current=element;while(!found){current=current.parentNode;if(current!=null){var ref=current.getAttribute("jfreesvg:ref");if(ref=="ORSON_CHART_TOP_LEVEL"){found=true;id=current.getAttribute("id")}}else found=true}return id};if(!orsoncharts)orsoncharts={};orsoncharts.KeyedValuesDataset=function(){if(!(this instanceof orsoncharts.KeyedValuesDataset))return new orsoncharts.KeyedValuesDataset;this.data=[];this.listeners=[]};orsoncharts.KeyedValuesDataset.prototype.itemCount=function(){return this.data.length};orsoncharts.KeyedValuesDataset.prototype.isEmpty=function(){return this.data.length===0};orsoncharts.KeyedValuesDataset.prototype.key=function(index){return this.data[index][0]}; orsoncharts.KeyedValuesDataset.prototype.keys=function(){return this.data.map(function(d){return d[0]})};orsoncharts.KeyedValuesDataset.prototype.indexOf=function(sectionKey){var arrayLength=this.data.length;for(var i=0;i=0)this.listeners.splice(i,1)}; orsoncharts.KeyedValuesDataset.prototype.notifyListeners=function(){};orsoncharts.KeyedValuesDataset.prototype.add=function(sectionKey,value){this.data.push([sectionKey,value])};orsoncharts.KeyedValuesDataset.prototype.remove=function(sectionKey){if(!sectionKey)throw new Error("The 'sectionKey' must be defined.");var i=this.indexOf(sectionKey);if(i<0)throw new Error("The sectionKey '"+sectionKey.toString()+"' is not recognised.");this.data.splice(i,1)}; orsoncharts.KeyedValuesDataset.prototype.dataFromJSON=function(jsonStr){this.data=JSON.parse(jsonStr);this.notifyListeners()};orsoncharts.KeyedValuesDataset.prototype.removeByIndex=function(itemIndex){this.data.splice(itemIndex,1)};orsoncharts.KeyedValuesDataset.prototype.totalForDataset=function(dataset){var total=0;var itemCount=dataset.itemCount();for(var i=0;i=0)this.listeners.splice(i,1)};orsoncharts.KeyedValues3DDataset.prototype.notifyListeners=function(){}; orsoncharts.KeyedValues3DDataset.prototype.add=function(seriesKey,rowKey,columnKey,value){if(this.isEmpty()){this.data.rowKeys.push(rowKey);this.data.columnKeys.push(columnKey);this.data.series.push({"seriesKey":seriesKey,"rows":[[rowKey,[value]]]})}else{var seriesIndex=this.seriesIndex(seriesKey);if(seriesIndex<0){this.data.series.push({"seriesKey":seriesKey,"rows":[]});seriesIndex=this.data.series.length-1}var columnIndex=this.columnIndex(columnKey);if(columnIndex<0){this.data.columnKeys.push(columnKey); for(var s=0;s=0)throw new Error("There is already a series with the key '"+seriesKey);this.data["series"].push([seriesKey,[]])}; orsoncharts.XYZDataset.prototype.removeSeries=function(seriesKey){if(!(typeof seriesKey==="string"))throw new Error("The 'seriesKey' must be a string.");var s=this.seriesIndex(seriesKey);if(s>=0)this.data["series"].splice(s,1)};orsoncharts.XYZDataset.prototype.addListener=function(listenerMethod){this.listeners.push(listenerMethod)};orsoncharts.XYZDataset.prototype.removeListener=function(listenerMethod){var i=this.listeners.indexOf(listenerMethod);if(i>=0)this.listeners.splice(i,1)};if(!orsoncharts)orsoncharts={};orsoncharts.KeyedValueLabels=function(){if(!(this instanceof orsoncharts.KeyedValueLabels))return new orsoncharts.KeyedValueLabels;this.format="{K} = {V}";this.valueDP=2;this.percentDP=2}; orsoncharts.KeyedValueLabels.prototype.itemLabel=function(keyedValues,itemIndex){var labelStr=new String(this.format);var keyStr=keyedValues.key(itemIndex);var value=keyedValues.valueByIndex(itemIndex);var valueStr=value.toFixed(this.valueDP);var total=keyedValues.total();var percentStr=(value/total*100).toFixed(this.percentDP);labelStr=labelStr.replace(/{K}/g,keyStr);labelStr=labelStr.replace(/{V}/g,valueStr);labelStr=labelStr.replace(/{P}/g,percentStr);return labelStr};if(!orsoncharts)orsoncharts={};orsoncharts.KeyedValue3DLabels=function(){if(!(this instanceof orsoncharts.KeyedValue3DLabels))return new orsoncharts.KeyedValue3DLabels;this.format="{S}, {R}, {C} = {V}";this.valueDP=2}; orsoncharts.KeyedValue3DLabels.prototype.itemLabel=function(keyedValues3D,seriesIndex,rowIndex,columnIndex){var labelStr=new String(this.format);var seriesKeyStr=keyedValues3D.seriesKey(seriesIndex);var rowKeyStr=keyedValues3D.rowKey(rowIndex);var columnKeyStr=keyedValues3D.columnKey(columnIndex);var value=keyedValues3D.valueByIndex(seriesIndex,rowIndex,columnIndex);var valueStr=value.toFixed(this.valueDP);labelStr=labelStr.replace(/{S}/g,seriesKeyStr);labelStr=labelStr.replace(/{R}/g,rowKeyStr); labelStr=labelStr.replace(/{C}/g,columnKeyStr);labelStr=labelStr.replace(/{V}/g,valueStr);return labelStr};if(!orsoncharts)orsoncharts={};orsoncharts.XYZLabels=function(){if(!(this instanceof orsoncharts.XYZLabels))return new orsoncharts.XYZLabels;this.format="{X}, {Y}, {Z} / {S}";this.xDP=2;this.yDP=2;this.zDP=2}; orsoncharts.XYZLabels.prototype.itemLabel=function(dataset,seriesKey,itemIndex){var labelStr=new String(this.format);var seriesKeyStr=seriesKey;var seriesIndex=dataset.seriesIndex(seriesKey);var item=dataset.item(seriesIndex,itemIndex);var xStr=item[0].toFixed(this.xDP);var yStr=item[1].toFixed(this.yDP);var zStr=item[2].toFixed(this.zDP);labelStr=labelStr.replace(/{X}/g,xStr);labelStr=labelStr.replace(/{Y}/g,yStr);labelStr=labelStr.replace(/{Z}/g,zStr);labelStr=labelStr.replace(/{S}/g,seriesKeyStr); return labelStr};