Browse files

Initial import.

  • Loading branch information...
1 parent 62c7b18 commit 1d27308e81f1a6bacb500daffc551a74645b436e @jdf committed Jan 9, 2009
View
7 .classpath
@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<classpath>
+ <classpathentry kind="src" path="src"/>
+ <classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/jdk1.5.0_14"/>
+ <classpathentry combineaccessrules="false" kind="src" path="/processing-head"/>
+ <classpathentry kind="output" path="bin"/>
+</classpath>
View
17 .project
@@ -0,0 +1,17 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<projectDescription>
+ <name>PeasyCam</name>
+ <comment></comment>
+ <projects>
+ </projects>
+ <buildSpec>
+ <buildCommand>
+ <name>org.eclipse.jdt.core.javabuilder</name>
+ <arguments>
+ </arguments>
+ </buildCommand>
+ </buildSpec>
+ <natures>
+ <nature>org.eclipse.jdt.core.javanature</nature>
+ </natures>
+</projectDescription>
View
12 .settings/org.eclipse.jdt.core.prefs
@@ -0,0 +1,12 @@
+#Fri Jan 09 08:33:47 EST 2009
+eclipse.preferences.version=1
+org.eclipse.jdt.core.compiler.codegen.inlineJsrBytecode=enabled
+org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.5
+org.eclipse.jdt.core.compiler.codegen.unusedLocal=preserve
+org.eclipse.jdt.core.compiler.compliance=1.5
+org.eclipse.jdt.core.compiler.debug.lineNumber=generate
+org.eclipse.jdt.core.compiler.debug.localVariable=generate
+org.eclipse.jdt.core.compiler.debug.sourceFile=generate
+org.eclipse.jdt.core.compiler.problem.assertIdentifier=error
+org.eclipse.jdt.core.compiler.problem.enumIdentifier=error
+org.eclipse.jdt.core.compiler.source=1.5
View
202 commons-math-1.2/LICENSE.txt
@@ -0,0 +1,202 @@
+
+ Apache License
+ Version 2.0, January 2004
+ http://www.apache.org/licenses/
+
+ TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
+
+ 1. Definitions.
+
+ "License" shall mean the terms and conditions for use, reproduction,
+ and distribution as defined by Sections 1 through 9 of this document.
+
+ "Licensor" shall mean the copyright owner or entity authorized by
+ the copyright owner that is granting the License.
+
+ "Legal Entity" shall mean the union of the acting entity and all
+ other entities that control, are controlled by, or are under common
+ control with that entity. For the purposes of this definition,
+ "control" means (i) the power, direct or indirect, to cause the
+ direction or management of such entity, whether by contract or
+ otherwise, or (ii) ownership of fifty percent (50%) or more of the
+ outstanding shares, or (iii) beneficial ownership of such entity.
+
+ "You" (or "Your") shall mean an individual or Legal Entity
+ exercising permissions granted by this License.
+
+ "Source" form shall mean the preferred form for making modifications,
+ including but not limited to software source code, documentation
+ source, and configuration files.
+
+ "Object" form shall mean any form resulting from mechanical
+ transformation or translation of a Source form, including but
+ not limited to compiled object code, generated documentation,
+ and conversions to other media types.
+
+ "Work" shall mean the work of authorship, whether in Source or
+ Object form, made available under the License, as indicated by a
+ copyright notice that is included in or attached to the work
+ (an example is provided in the Appendix below).
+
+ "Derivative Works" shall mean any work, whether in Source or Object
+ form, that is based on (or derived from) the Work and for which the
+ editorial revisions, annotations, elaborations, or other modifications
+ represent, as a whole, an original work of authorship. For the purposes
+ of this License, Derivative Works shall not include works that remain
+ separable from, or merely link (or bind by name) to the interfaces of,
+ the Work and Derivative Works thereof.
+
+ "Contribution" shall mean any work of authorship, including
+ the original version of the Work and any modifications or additions
+ to that Work or Derivative Works thereof, that is intentionally
+ submitted to Licensor for inclusion in the Work by the copyright owner
+ or by an individual or Legal Entity authorized to submit on behalf of
+ the copyright owner. For the purposes of this definition, "submitted"
+ means any form of electronic, verbal, or written communication sent
+ to the Licensor or its representatives, including but not limited to
+ communication on electronic mailing lists, source code control systems,
+ and issue tracking systems that are managed by, or on behalf of, the
+ Licensor for the purpose of discussing and improving the Work, but
+ excluding communication that is conspicuously marked or otherwise
+ designated in writing by the copyright owner as "Not a Contribution."
+
+ "Contributor" shall mean Licensor and any individual or Legal Entity
+ on behalf of whom a Contribution has been received by Licensor and
+ subsequently incorporated within the Work.
+
+ 2. Grant of Copyright License. Subject to the terms and conditions of
+ this License, each Contributor hereby grants to You a perpetual,
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+ copyright license to reproduce, prepare Derivative Works of,
+ publicly display, publicly perform, sublicense, and distribute the
+ Work and such Derivative Works in Source or Object form.
+
+ 3. Grant of Patent License. Subject to the terms and conditions of
+ this License, each Contributor hereby grants to You a perpetual,
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+ (except as stated in this section) patent license to make, have made,
+ use, offer to sell, sell, import, and otherwise transfer the Work,
+ where such license applies only to those patent claims licensable
+ by such Contributor that are necessarily infringed by their
+ Contribution(s) alone or by combination of their Contribution(s)
+ with the Work to which such Contribution(s) was submitted. If You
+ institute patent litigation against any entity (including a
+ cross-claim or counterclaim in a lawsuit) alleging that the Work
+ or a Contribution incorporated within the Work constitutes direct
+ or contributory patent infringement, then any patent licenses
+ granted to You under this License for that Work shall terminate
+ as of the date such litigation is filed.
+
+ 4. Redistribution. You may reproduce and distribute copies of the
+ Work or Derivative Works thereof in any medium, with or without
+ modifications, and in Source or Object form, provided that You
+ meet the following conditions:
+
+ (a) You must give any other recipients of the Work or
+ Derivative Works a copy of this License; and
+
+ (b) You must cause any modified files to carry prominent notices
+ stating that You changed the files; and
+
+ (c) You must retain, in the Source form of any Derivative Works
+ that You distribute, all copyright, patent, trademark, and
+ attribution notices from the Source form of the Work,
+ excluding those notices that do not pertain to any part of
+ the Derivative Works; and
+
+ (d) If the Work includes a "NOTICE" text file as part of its
+ distribution, then any Derivative Works that You distribute must
+ include a readable copy of the attribution notices contained
+ within such NOTICE file, excluding those notices that do not
+ pertain to any part of the Derivative Works, in at least one
+ of the following places: within a NOTICE text file distributed
+ as part of the Derivative Works; within the Source form or
+ documentation, if provided along with the Derivative Works; or,
+ within a display generated by the Derivative Works, if and
+ wherever such third-party notices normally appear. The contents
+ of the NOTICE file are for informational purposes only and
+ do not modify the License. You may add Your own attribution
+ notices within Derivative Works that You distribute, alongside
+ or as an addendum to the NOTICE text from the Work, provided
+ that such additional attribution notices cannot be construed
+ as modifying the License.
+
+ You may add Your own copyright statement to Your modifications and
+ may provide additional or different license terms and conditions
+ for use, reproduction, or distribution of Your modifications, or
+ for any such Derivative Works as a whole, provided Your use,
+ reproduction, and distribution of the Work otherwise complies with
+ the conditions stated in this License.
+
+ 5. Submission of Contributions. Unless You explicitly state otherwise,
+ any Contribution intentionally submitted for inclusion in the Work
+ by You to the Licensor shall be under the terms and conditions of
+ this License, without any additional terms or conditions.
+ Notwithstanding the above, nothing herein shall supersede or modify
+ the terms of any separate license agreement you may have executed
+ with Licensor regarding such Contributions.
+
+ 6. Trademarks. This License does not grant permission to use the trade
+ names, trademarks, service marks, or product names of the Licensor,
+ except as required for reasonable and customary use in describing the
+ origin of the Work and reproducing the content of the NOTICE file.
+
+ 7. Disclaimer of Warranty. Unless required by applicable law or
+ agreed to in writing, Licensor provides the Work (and each
+ Contributor provides its Contributions) on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+ implied, including, without limitation, any warranties or conditions
+ of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
+ PARTICULAR PURPOSE. You are solely responsible for determining the
+ appropriateness of using or redistributing the Work and assume any
+ risks associated with Your exercise of permissions under this License.
+
+ 8. Limitation of Liability. In no event and under no legal theory,
+ whether in tort (including negligence), contract, or otherwise,
+ unless required by applicable law (such as deliberate and grossly
+ negligent acts) or agreed to in writing, shall any Contributor be
+ liable to You for damages, including any direct, indirect, special,
+ incidental, or consequential damages of any character arising as a
+ result of this License or out of the use or inability to use the
+ Work (including but not limited to damages for loss of goodwill,
+ work stoppage, computer failure or malfunction, or any and all
+ other commercial damages or losses), even if such Contributor
+ has been advised of the possibility of such damages.
+
+ 9. Accepting Warranty or Additional Liability. While redistributing
+ the Work or Derivative Works thereof, You may choose to offer,
+ and charge a fee for, acceptance of support, warranty, indemnity,
+ or other liability obligations and/or rights consistent with this
+ License. However, in accepting such obligations, You may act only
+ on Your own behalf and on Your sole responsibility, not on behalf
+ of any other Contributor, and only if You agree to indemnify,
+ defend, and hold each Contributor harmless for any liability
+ incurred by, or claims asserted against, such Contributor by reason
+ of your accepting any such warranty or additional liability.
+
+ END OF TERMS AND CONDITIONS
+
+ APPENDIX: How to apply the Apache License to your work.
+
+ To apply the Apache License to your work, attach the following
+ boilerplate notice, with the fields enclosed by brackets "[]"
+ replaced with your own identifying information. (Don't include
+ the brackets!) The text should be enclosed in the appropriate
+ comment syntax for the file format. We also recommend that a
+ file or class name and description of purpose be included on the
+ same "printed page" as the copyright notice for easier
+ identification within third-party archives.
+
+ Copyright [yyyy] [name of copyright owner]
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
View
97 commons-math-1.2/NOTICE.txt
@@ -0,0 +1,97 @@
+Apache Commons Math
+Copyright 2001-2008 The Apache Software Foundation
+
+This product includes software developed by
+The Apache Software Foundation (http://www.apache.org/).
+
+
+This product includes software translated from the lmder, lmpar
+and qrsolv Fortran routines from the Minpack package and
+distributed under the following disclaimer:
+
+---------- http://www.netlib.org/minpack/disclaimer ----------
+Minpack Copyright Notice (1999) University of Chicago. All rights reserved
+
+Redistribution and use in source and binary forms, with or
+without modification, are permitted provided that the
+following conditions are met:
+
+1. Redistributions of source code must retain the above
+copyright notice, this list of conditions and the following
+disclaimer.
+
+2. Redistributions in binary form must reproduce the above
+copyright notice, this list of conditions and the following
+disclaimer in the documentation and/or other materials
+provided with the distribution.
+
+3. The end-user documentation included with the
+redistribution, if any, must include the following
+acknowledgment:
+
+ "This product includes software developed by the
+ University of Chicago, as Operator of Argonne National
+ Laboratory.
+
+Alternately, this acknowledgment may appear in the software
+itself, if and wherever such third-party acknowledgments
+normally appear.
+
+4. WARRANTY DISCLAIMER. THE SOFTWARE IS SUPPLIED "AS IS"
+WITHOUT WARRANTY OF ANY KIND. THE COPYRIGHT HOLDER, THE
+UNITED STATES, THE UNITED STATES DEPARTMENT OF ENERGY, AND
+THEIR EMPLOYEES: (1) DISCLAIM ANY WARRANTIES, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO ANY IMPLIED WARRANTIES
+OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, TITLE
+OR NON-INFRINGEMENT, (2) DO NOT ASSUME ANY LEGAL LIABILITY
+OR RESPONSIBILITY FOR THE ACCURACY, COMPLETENESS, OR
+USEFULNESS OF THE SOFTWARE, (3) DO NOT REPRESENT THAT USE OF
+THE SOFTWARE WOULD NOT INFRINGE PRIVATELY OWNED RIGHTS, (4)
+DO NOT WARRANT THAT THE SOFTWARE WILL FUNCTION
+UNINTERRUPTED, THAT IT IS ERROR-FREE OR THAT ANY ERRORS WILL
+BE CORRECTED.
+
+5. LIMITATION OF LIABILITY. IN NO EVENT WILL THE COPYRIGHT
+HOLDER, THE UNITED STATES, THE UNITED STATES DEPARTMENT OF
+ENERGY, OR THEIR EMPLOYEES: BE LIABLE FOR ANY INDIRECT,
+INCIDENTAL, CONSEQUENTIAL, SPECIAL OR PUNITIVE DAMAGES OF
+ANY KIND OR NATURE, INCLUDING BUT NOT LIMITED TO LOSS OF
+PROFITS OR LOSS OF DATA, FOR ANY REASON WHATSOEVER, WHETHER
+SUCH LIABILITY IS ASSERTED ON THE BASIS OF CONTRACT, TORT
+(INCLUDING NEGLIGENCE OR STRICT LIABILITY), OR OTHERWISE,
+EVEN IF ANY OF SAID PARTIES HAS BEEN WARNED OF THE
+POSSIBILITY OF SUCH LOSS OR DAMAGES.
+---------- http://www.netlib.org/minpack/disclaimer ----------
+
+
+
+This product includes software translated from the odex Fortran routine
+developed by E. Hairer and G. Wanner and distributed under the following
+license:
+
+---------- http://www.unige.ch/~hairer/prog/licence.txt ----------
+Copyright (c) 2004, Ernst Hairer
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are
+met:
+
+- Redistributions of source code must retain the above copyright
+notice, this list of conditions and the following disclaimer.
+
+- Redistributions in binary form must reproduce the above copyright
+notice, this list of conditions and the following disclaimer in the
+documentation and/or other materials provided with the distribution.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
+IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
+PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR
+CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+---------- http://www.unige.ch/~hairer/prog/licence.txt ----------
View
11 commons-math-1.2/PEASY-README.txt
@@ -0,0 +1,11 @@
+PeasyCam uses a tiny subset of the commons math project, to wit,
+the geometry routines. Per the rights outlined in its
+Apache License, I've "modified" commons math by throwing eveything
+away that isn't the geometry routines.
+
+In order to avoid conflicts with other instances of commons math in
+a user's classpath, I've modified the packages.
+
+The complete commons math library is available at
+
+ http://commons.apache.org/math/
View
161 commons-math-1.2/RELEASE-NOTES.txt
@@ -0,0 +1,161 @@
+
+ Apache Commons Math Version 1.2
+ RELEASE NOTES
+
+
+This release combines bug fixes and new features. Most notable among the new
+features are the estimation, optimization, geometry and ode packages added
+from the Mantissa library. Implementations of fast Fourier transform, QR
+decomposition and several numerical integration algorithms have also been
+added, along with enhancements and extensions to packages included in Commons
+Math 1.1. This release is source and binary compatible with earlier versions
+of Commons Math.
+
+For more information on Apache Commons Math, see
+http://commons.apache.org/math/
+
+
+ SUMMARY OF CHANGES
+
+ADDITIONS
+
+* Added the estimation, optimization, geometry and ode packages from the
+ Mantissa library.
+
+* MATH-120. Added Pascal distribution implementation. Thanks to Todd C.
+ Parnell.
+
+* MATH-148. Added QR Decomposition. Thanks to Joni Salonen.
+
+* MATH-140. Added Fast Fourier Transform implementation. Thanks to Xiaogang
+ Zhang.
+
+* MATH-173. Added one-way ANOVA implementation. Thanks to Bob MacCallum.
+
+* Added an angle normalization method in MathUtils to force angles in some
+ user-defined interval
+
+* Added vectorial covariance computation (either sample or population
+ covariance)
+
+* Added multivariate summary statistics.
+
+
+BUG FIXES
+
+* Fixed numerous warnings in test code.
+
+* MATH-156. Use the initial guess provided by the user in
+ BrentSolver.solve(), thus improving speed. Thanks to Tyler Ward.
+
+* MATH-18. Made ComplexFormat format double values with a provided
+ NumberFormat instance instead of using the real part format for all values.
+ Thanks to Phil Steitz.
+
+* MATH-60. Modified ProperFractionFormat to reject embedded minus signs.
+ Thanks to Nhung Nnguyen.
+
+* MATH-151. Added a nextAfter method in MathUtils to return the next
+ machine-representable number in a specified direction from a given floating
+ point number. Used this to ensure that MathUtils.round does not return
+ incorrect results for numbers with bad IEEE754 representations. Thanks to
+ Luc Maisonobe.
+
+* MATH-85. Modified getSumSquaredErrors method in SimpleRegression to always
+ return a non-negative result. Thanks to Mark Osborn, Luc Maisonobe.
+
+* MATH-153. Corrected nextInt and nextLong to handle wide value ranges.
+ Thanks to Remi Arntzen.
+
+* MATH-166. Increased default precision of Gamma and Beta functions. Thanks
+ to Lukas Theussl.
+
+* MATH-167. Modified NormalDistributionImpl.cumulativeProbablity to catch
+ MaxIterationsExceededException and return 0 or 1, resp. if the argument is
+ more than 20 standard deviations from the mean.
+
+* MATH-174. Changed Mean.evaluate() to use a two-pass algorithm, improving
+ accuracy by exploiting the the fact that this method has access to the full
+ array of data values.
+
+* MATH-175. Added check and rescaling of expected counts to sum to sum of
+ expected counts if necessary in ChiSquare test. Thanks to Carl Anderson.
+
+* MATH-164. Handle multiplication of Complex numbers with infinite parts
+ specially.
+
+* MATH-182. Add integer overflow checks in Fraction constructor using double
+ parameter.
+
+* MATH-185. Throw EOFException when using empty files with ValueServer in
+ replay and digest modes.
+
+* MATH-184. Fixed AbstractIntegerDistribution cumulativeProbablility(-,-) to
+ correctly handle double arguments. Thanks to Yegor Bryukhov.
+
+
+UPDATES
+
+* MATH-158. Added log function to MathUtils. Thanks to Hasan Diwan.
+
+* MATH-160. Added two sample (binned comparison) ChiSquare test. Thanks to
+ Matthias Hummel.
+
+* MATH-170. Added SynchronizedDescriptiveStatistics class. Thanks to David J.
+ M. Karlsen.
+
+* MATH-154. Added addAndCheck, mulAndCheck, and subAndCheck MathUtils methods
+ for long integer arguments. Thanks to Remi Arntzen.
+
+* MATH-171. Merged most functions from ComplexUtils into Complex class, added
+ static factory method to Complex. Thanks to Niall Pemberton.
+
+* Deprecated abstract factory methods and made DescriptiveStatistics and and
+ SummaryStatistics concrete classes. Pushed implementations up from
+ DescriptiveStatisticsImpl, SummaryStatisticsImpl. Made implementations of
+ statistics configurable via setters.
+
+* MATH-176. Add errors guessing to least-squares estimators. Thanks to
+ Kazuhiro Koshino.
+
+* MATH-179. Add tests for Fraction constructor using double parameter. Thanks
+ to Niall Pemberton.
+
+* MATH-181. Add Fraction constructor using max denominator value. Thanks to
+ Niall Pemberton.
+
+* Added a equals and hash methods in MathUtils to check for double arrays
+
+* MATH-191. Added getSumOfLogs method to SummaryStatistics and made SumOfLogs
+ instance used by GeometricMean configurable.
+
+* MATH-188. Made numerator and denominator final in Fraction and deprecated
+ protected real and imaginary parts fields in Complex, making Fraction
+ immutable and preparing Complex to become fully immutable in 2.0. Thanks to
+ Sebastian Bazley.
+
+DEPRECATIONS SUMMARY
+
+* The abstract factory pattern used to enable pluggable implementations in the
+ statistics, analysis and distributions packages has been deprecated and
+ replaced by setter injection.
+
+* Non-localized exception messages and associated constructors have been
+ deprecated and replaced by localized versions.
+
+* Most methods from the ComplexUtils class have been deprecated, with
+ implementations moved to the Complex class.
+
+See "clirr-report.html" included in the docs directory of the binary
+distribution for a detailed list of API changes. The "errors" reported at the
+top of the report are due to protected fields being moved to superclasses.
+These fields are still available, so there is no backward compatibility issue.
+
+BUILDING COMMONS MATH
+
+Commons math can be built from the source distribution using Maven 1, Maven 2,
+or Ant, launching any one of these from the top-level directory of the unpacked
+zip or tarball. For detailed build instructions and information about how to
+contribute to Commons Math, see "developers.html" in the docs directory of the
+binary distribution.
+
View
22 examples/HelloPeasy/HelloPeasy.pde
@@ -0,0 +1,22 @@
+import peasy.*;
+
+PeasyCam cam;
+
+void setup() {
+ size(400,400,P3D);
+ cam = new PeasyCam(this, 100);
+ cam.rotateX(.5);
+ cam.rotateY(.5);
+}
+void draw() {
+ background(0);
+ fill(255,0,0);
+ box(30);
+ pushMatrix();
+ translate(0,0,-20);
+ fill(0,0,255);
+ box(5);
+ popMatrix();
+}
+
+
View
198 resources/build.xml
@@ -0,0 +1,198 @@
+<project name="processingLibs" default="build" basedir="../">
+
+ <description>
+ PeasyCam build
+ </description>
+
+ <property name="processing" location="c:/Documents and Settings/Administrator/Desktop/processing-1.0.1/libraries" />
+
+ <property name="libraryClasspath" location="${processing}/../lib" />
+ <path id="library-classpath">
+ <fileset dir="${libraryClasspath}">
+ <include name="core.jar" />
+ </fileset>
+ </path>
+
+ <property name="javaVersion" value="1.5" />
+
+ <property name="author" value="Jonathan Feinberg" />
+ <property name="copyright" value="(c) 2008" />
+ <property name="libraryName" value="PeasyCam" />
+ <property name="versionNumber" value="0.1.0" />
+ <property name="yourLink" value="http://mrfeinberg.com" />
+ <property name="keywords" value="3D,camera,rotation" />
+ <property name="tested:platform" value="Windows" />
+ <property name="tested:processingVersion" value="1.0" />
+ <property name="tested:dependencies" value="" />
+ <property name="source:host" value="google code" />
+ <property name="source:url" value="http://code.google.com/p/peasycam" />
+ <property name="source:repository" value="http://code.google.com/p/peasycam/source/browse/" />
+
+
+ <!-- no changes or adjustments required below -->
+
+ <taskdef resource="net/sf/antcontrib/antcontrib.properties">
+ <classpath>
+ <pathelement location="./resources/code/ant-contrib-1.0b3.jar" />
+ </classpath>
+ </taskdef>
+ <property name="jarFile" value="${libraryName}.jar" />
+ <property name="src" location="src" />
+ <property name="bin" location="bin" />
+ <property name="reference" location="reference" />
+ <property name="dist" location="distribution" />
+
+
+
+ <target name="init">
+ <echo>Properties initialized.
+ src path ${src}
+ bin path ${bin}
+ libraryClasspath ${libraryClasspath}
+ processing Libraries ${processing}
+ java version ${javaVersion}
+ </echo>
+ <echo>building library ...</echo>
+ <!-- Create the time stamp -->
+ <tstamp>
+ <format property="date" pattern="MM/dd/yyyy" offset="0" unit="hour" />
+ </tstamp>
+ <mkdir dir="${dist}" />
+ </target>
+
+ <!-- compile the library -->
+ <target name="compile" depends="init" description="compile the source">
+ <javac destdir="${bin}" source="${javaVersion}">
+ <classpath>
+ <path refid="library-classpath" />
+ </classpath>
+ <src path="${src}" />
+ </javac>
+ </target>
+
+ <!-- build the distribution of the library -->
+ <target name="build" depends="compile" description="generate the distribution">
+ <!-- delete the previous content of the ${dist} folder -->
+ <delete dir="${dist}" />
+
+ <!-- build the structure for ${dist} -->
+ <mkdir dir="${dist}" />
+
+ <property name="realDist" value="${dist}/peasycam"/>
+ <mkdir dir="${realDist}" />
+
+ <mkdir dir="${realDist}/library" />
+ <mkdir dir="${realDist}/examples" />
+ <mkdir dir="${realDist}/reference" />
+ <mkdir dir="${realDist}/src" />
+ <jar jarfile="${realDist}/library/${jarFile}" basedir="${bin}" />
+ <copy todir="${realDist}/examples">
+ <fileset dir="examples" />
+ </copy>
+ <copy todir="${realDist}/src">
+ <fileset dir="src" />
+ </copy>
+
+ <!-- create the java reference of the library -->
+ <mkdir dir="${reference}" />
+ <javadoc bottom="processing library ${libraryName} by ${author}. ${copyright}" classpath="${libraryClasspath}/core.jar" destdir="${reference}" verbose="false" stylesheetfile="resources/stylesheet.css" doctitle="Javadocs: ${libraryName}" public="true" version="false" windowtitle="Javadocs: ${libraryName}">
+ <taglet name="ExampleTaglet" path="resources/code" />
+ <fileset dir="${src}" defaultexcludes="yes">
+ <!-- #### (9) add packages to be added to reference. #### -->
+ <include name="**/*" />
+ </fileset>
+ </javadoc>
+
+ <copy todir="${realDist}/reference">
+ <fileset dir="${reference}" />
+ </copy>
+
+ <!-- copy the jar file to processing's libraries -->
+ <copy todir="${processing}">
+ <fileset dir="${dist}" />
+ </copy>
+
+ <!-- zip the distribution of the library -->
+ <zip destfile="${dist}/${libraryName}.zip" basedir="${dist}" excludes="**/_DS.Store" />
+
+ <!-- <rename src="${dist}/${libraryName}.zip" dest="${dist}/${libraryName}_${versionNumber}.zip" /> -->
+
+ <!-- organize the ${dist} folder -->
+ <mkdir dir="${dist}/web" />
+ <move todir="${dist}/web/reference">
+ <fileset dir="${realDist}/reference" />
+ </move>
+
+ <move todir="${dist}/web/examples">
+ <fileset dir="${realDist}/examples" />
+ </move>
+
+ <delete dir="${dist}/library" />
+
+ <copy todir="${dist}/web">
+ <fileset dir="web" />
+ </copy>
+
+ <!--
+ format the index.html file.
+ regular expressions are used to parse the web index.html file.
+ key words starting and ending with ## are replaced by values
+ defined earlier in the beginning of this build file.
+ -->
+
+ <replaceregexp file="${dist}/web/index.html" match="##yourLibrary##" replace="${libraryName}" flags="g" />
+
+ <replaceregexp file="${dist}/web/index.html" match="##author##" replace="${author}" flags="g" />
+
+ <replaceregexp file="${dist}/web/index.html" match="##versionNumber##" replace="${versionNumber}" flags="g" />
+
+ <replaceregexp file="${dist}/web/index.html" match="##yourLink##" replace="${yourLink}" flags="g" />
+
+ <replaceregexp file="${dist}/web/index.html" match="##date##" replace="${date}" flags="g" />
+
+ <replaceregexp file="${dist}/web/index.html" match="##keywords##" replace="${keywords}" flags="g" />
+
+
+
+ <replaceregexp file="${dist}/web/index.html" match="##tested:platform##" replace="${tested:platform}" flags="g" />
+ <replaceregexp file="${dist}/web/index.html" match="##tested:processingVersion##" replace="${tested:processingVersion}" flags="g" />
+ <replaceregexp file="${dist}/web/index.html" match="##tested:dependencies##" replace="${tested:dependencies}" flags="g" />
+ <replaceregexp file="${dist}/web/index.html" match="##source:host##" replace="${source:host}" flags="g" />
+ <replaceregexp file="${dist}/web/index.html" match="##source:url##" replace="${source:url}" flags="g" />
+ <replaceregexp file="${dist}/web/index.html" match="##source:repository##" replace="${source:repository}" flags="g" />
+
+
+ <echo>---------------------</echo>
+ <antcall target="processExamples" />
+ <echo>---------------------</echo>
+
+ <replaceregexp file="${dist}/web/index.html" match="##examples##" replace="" flags="g" />
+
+
+ <!-- finish organizating library's distribution -->
+ <mkdir dir="${dist}/web/download" />
+ <copy file="${dist}/${libraryName}.zip" todir="${dist}/web/download" />
+
+ <copy todir="${processing}/${libraryName}/reference">
+ <fileset dir="${reference}" />
+ </copy>
+
+ <!-- done, finished. -->
+ <echo>done, finished.</echo>
+ </target>
+
+
+
+ <!-- parsing the examples folder -->
+ <target name="processExamples">
+ <dirset id="examples.contents" dir="examples" excludes="*/*" />
+ <property name="examples.list" refid="examples.contents" />
+ <foreach list="${examples.list}" target="addExamples" param="exampleDir" delimiter=";">
+ </foreach>
+ </target>
+
+ <target name="addExamples">
+ <replaceregexp file="${dist}/web/index.html" match="(##examples##)" replace="&lt;li&gt;&lt;a href=&quot;examples/${exampleDir}/${exampleDir}.pde&quot;&gt;${exampleDir}&lt;/a&gt;&lt;/li&gt; \1" flags="g" />
+ </target>
+</project>
+
View
231 resources/code/ExampleTaglet.java
@@ -0,0 +1,231 @@
+/*
+ * Copyright 2002 Sun Microsystems, Inc. All Rights Reserved.
+ *
+ * Redistribution and use in source and binary forms, with or
+ * without modification, are permitted provided that the following
+ * conditions are met:
+ *
+ * -Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * -Redistribution in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ *
+ * Neither the name of Sun Microsystems, Inc. or the names of
+ * contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * This software is provided "AS IS," without a warranty of any
+ * kind. ALL EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND
+ * WARRANTIES, INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT, ARE HEREBY
+ * EXCLUDED. SUN AND ITS LICENSORS SHALL NOT BE LIABLE FOR ANY
+ * DAMAGES OR LIABILITIES SUFFERED BY LICENSEE AS A RESULT OF OR
+ * RELATING TO USE, MODIFICATION OR DISTRIBUTION OF THE SOFTWARE OR
+ * ITS DERIVATIVES. IN NO EVENT WILL SUN OR ITS LICENSORS BE LIABLE
+ * FOR ANY LOST REVENUE, PROFIT OR DATA, OR FOR DIRECT, INDIRECT,
+ * SPECIAL, CONSEQUENTIAL, INCIDENTAL OR PUNITIVE DAMAGES, HOWEVER
+ * CAUSED AND REGARDLESS OF THE THEORY OF LIABILITY, ARISING OUT OF
+ * THE USE OF OR INABILITY TO USE SOFTWARE, EVEN IF SUN HAS BEEN
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
+ *
+ * You acknowledge that Software is not designed, licensed or
+ * intended for use in the design, construction, operation or
+ * maintenance of any nuclear facility.
+ */
+
+import com.sun.tools.doclets.Taglet;
+import com.sun.javadoc.*;
+import java.util.Map;
+import java.io.*;
+/**
+ * A sample Taglet representing @example. This tag can be used in any kind of
+ * {@link com.sun.javadoc.Doc}. It is not an inline tag. The text is displayed
+ * in yellow to remind the developer to perform a task. For
+ * example, "@example Hello" would be shown as:
+ * <DL>
+ * <DT>
+ * <B>To Do:</B>
+ * <DD><table cellpadding=2 cellspacing=0><tr><td bgcolor="yellow">Fix this!
+ * </td></tr></table></DD>
+ * </DL>
+ *
+ * @author Jamie Ho
+ * @since 1.4
+ */
+
+public class ExampleTaglet implements Taglet {
+
+ private static final String NAME = "example";
+ private static final String HEADER = "example To Do:";
+
+ /**
+ * Return the name of this custom tag.
+ */
+ public String getName() {
+ return NAME;
+ }
+
+ /**
+ * Will return true since <code>@example</code>
+ * can be used in field documentation.
+ * @return true since <code>@example</code>
+ * can be used in field documentation and false
+ * otherwise.
+ */
+ public boolean inField() {
+ return true;
+ }
+
+ /**
+ * Will return true since <code>@example</code>
+ * can be used in constructor documentation.
+ * @return true since <code>@example</code>
+ * can be used in constructor documentation and false
+ * otherwise.
+ */
+ public boolean inConstructor() {
+ return true;
+ }
+
+ /**
+ * Will return true since <code>@example</code>
+ * can be used in method documentation.
+ * @return true since <code>@example</code>
+ * can be used in method documentation and false
+ * otherwise.
+ */
+ public boolean inMethod() {
+ return true;
+ }
+
+ /**
+ * Will return true since <code>@example</code>
+ * can be used in method documentation.
+ * @return true since <code>@example</code>
+ * can be used in overview documentation and false
+ * otherwise.
+ */
+ public boolean inOverview() {
+ return true;
+ }
+
+ /**
+ * Will return true since <code>@example</code>
+ * can be used in package documentation.
+ * @return true since <code>@example</code>
+ * can be used in package documentation and false
+ * otherwise.
+ */
+ public boolean inPackage() {
+ return true;
+ }
+
+ /**
+ * Will return true since <code>@example</code>
+ * can be used in type documentation (classes or interfaces).
+ * @return true since <code>@example</code>
+ * can be used in type documentation and false
+ * otherwise.
+ */
+ public boolean inType() {
+ return true;
+ }
+
+ /**
+ * Will return false since <code>@example</code>
+ * is not an inline tag.
+ * @return false since <code>@example</code>
+ * is not an inline tag.
+ */
+
+ public boolean isInlineTag() {
+ return false;
+ }
+
+ /**
+ * Register this Taglet.
+ * @param tagletMap the map to register this tag to.
+ */
+ public static void register(Map tagletMap) {
+ ExampleTaglet tag = new ExampleTaglet();
+ Taglet t = (Taglet) tagletMap.get(tag.getName());
+ if (t != null) {
+ tagletMap.remove(tag.getName());
+ }
+ tagletMap.put(tag.getName(), tag);
+ }
+
+ /**
+ * Given the <code>Tag</code> representation of this custom
+ * tag, return its string representation.
+ * @param tag the <code>Tag</code> representation of this custom tag.
+ */
+ public String toString(Tag tag) {
+ return createHTML(readFile(tag.text()));
+ }
+
+
+ /**
+ * Given an array of <code>Tag</code>s representing this custom
+ * tag, return its string representation.
+ * @param tags the array of <code>Tag</code>s representing of this custom tag.
+ */
+ public String toString(Tag[] tags) {
+ if (tags.length == 0) {
+ return null;
+ }
+ return createHTML(readFile(tags[0].text()));
+ }
+
+
+
+ String createHTML(String theString) {
+ if(theString!=null) {
+ String dd = "<script type=\"text/javascript\">\n" +
+ "<!--\n"+
+ "document.getElementsByTagName('html')[0].className = 'isjs';" +
+ "function toggle(dt) { var display, dd=dt; do{ dd = dd.nextSibling } while(dd.tagName!='DD'); toOpen =!dd.style.display;" +
+ "dd.style.display = toOpen? 'block':''; dt.getElementsByTagName('span')[0].innerHTML = toOpen? '-':'+' ; }\n" +
+ "-->\n</script>";
+
+ return dd+"\n<div id=\"test\" class=\"toggleList\">" +
+ "<dl><dt onclick=\"toggle(this);\"><span>+</span>Example</dt>" +
+ "<dd><pre>"+theString+"</pre>" +
+ "</dd></dl></div>";
+ }
+ return "";
+ }
+
+
+ /**
+ * check if the examples directory exists and return the example as given in the tag.
+ * @param theExample the name of the example
+ */
+ String readFile(String theExample) {
+ String record = "";
+ String myResult = "";
+ int recCount = 0;
+ String myDir = "../examples";
+ File file=new File(myDir);
+ if(file.exists()==false) {
+ myDir = "./examples";
+ }
+ try {
+ FileReader fr = new FileReader(myDir+"/"+theExample+"/"+theExample+".pde");
+ BufferedReader br = new BufferedReader(fr);
+ record = new String();
+ while ((record = br.readLine()) != null) {
+ myResult += record+"\n";
+ }
+ } catch (IOException e) {
+ System.out.println(e);
+ return null;
+ }
+ return myResult;
+ }
+}
+
+
View
BIN resources/code/ant-contrib-1.0b3.jar
Binary file not shown.
View
18 resources/code/doc.sh
@@ -0,0 +1,18 @@
+# a shell script to create a java documentation
+# for a processing library.
+#
+# make changes to the variables below so they
+# fit the structure of your library
+
+# the package name of your library
+package=peasy;
+
+# source folder location
+src=../src;
+
+# the destination folder of your documentation
+dest=../documentation;
+
+
+# compile the java documentation
+javadoc -d $dest -stylesheetfile ./stylesheet.css -sourcepath ${src} ${package}
View
310 resources/stylesheet.css
@@ -0,0 +1,310 @@
+/* Javadoc style sheet */
+/* Define colors, fonts and other style attributes here to override the defaults */
+/* processingLibs style by andreas schlegel, sojamo */
+
+
+body {
+ margin : 0;
+ padding : 0;
+ padding-left : 10px;
+ padding-right : 8px;
+ background-color : #FFFFFF;
+ font-family : Verdana, Geneva, Arial, Helvetica, sans-serif;
+ font-size : 100%;
+ font-size : 0.7em;
+ font-weight : normal;
+ line-height : normal;
+ margin-bottom:30px;
+}
+
+
+
+
+/* Headings */
+h1, h2, h3, h4, h5, th {
+ font-family :Arial, Helvetica, sans-serif;
+ font-size:1.2em;
+}
+
+
+p {
+ font-size : 1em;
+ width:80%;
+}
+
+pre, code {
+ font-family : "Courier New", Courier, monospace;
+ font-size : 12px;
+ line-height : normal;
+}
+
+
+
+table {
+ border:0;
+ margin-bottom:10px;
+ margin-top:10px;
+}
+
+
+tr, td {
+ border-top: 0px solid;
+ border-left: 0px solid;
+ padding-top:8px;
+ padding-bottom:8px;
+}
+
+
+
+hr {
+ border:0;
+ height:1px;
+ padding:0;
+ margin:0;
+ margin-bottom:4px;
+
+}
+
+
+
+dd, th, td, font {
+ font-size:1.0em;
+ line-height:1.0em;
+}
+
+
+
+dt {
+ margin-bottom:0px;
+}
+
+
+
+dd {
+ margin-top:2px;
+ margin-bottom:4px;
+}
+
+
+
+a {
+ text-decoration: underline;
+ font-weight: normal;
+}
+
+a:hover,
+a:active {
+ text-decoration: underline;
+ font-weight: normal;
+}
+
+a:visited,
+a:link:visited {
+ text-decoration: underline;
+ font-weight: normal;
+}
+
+
+img {
+ border: 0px solid #000000;
+}
+
+
+
+/* Navigation bar fonts */
+.NavBarCell1 {
+ border:0;
+}
+
+.NavBarCell1Rev {
+ border:0;
+}
+
+.NavBarFont1 {
+ font-family: Arial, Helvetica, sans-serif;
+ font-size:1.1em;
+}
+
+
+.NavBarFont1 b {
+ font-weight:normal;
+}
+
+
+
+.NavBarFont1:after, .NavBarFont1Rev:after {
+ font-weight:normal;
+ content: " \\";
+}
+
+
+.NavBarFont1Rev {
+ font-family: Arial, Helvetica, sans-serif;
+ font-size:1.1em;
+}
+
+.NavBarFont1Rev b {
+ font-family: Arial, Helvetica, sans-serif;
+ font-size:1.1em;
+ font-weight:normal;
+}
+
+.NavBarCell2 {
+ font-family: Arial, Helvetica, sans-serif;
+}
+
+.NavBarCell3 {
+ font-family: Arial, Helvetica, sans-serif;
+}
+
+
+
+font.FrameItemFont {
+ font-family: Helvetica, Arial, sans-serif;
+ font-size:1.1em;
+ line-height:1.1em;
+}
+
+font.FrameHeadingFont {
+ font-family: Helvetica, Arial, sans-serif;
+ line-height:32px;
+}
+
+/* Font used in left-hand frame lists */
+.FrameTitleFont {
+ font-family: Helvetica, Arial, sans-serif
+}
+
+
+.toggleList {
+ padding:0;
+ margin:0;
+ margin-top:12px;
+}
+
+.toggleList dt {
+ font-weight:bold;
+ font-size:12px;
+ font-family:arial,sans-serif;
+ padding:0px;
+ margin:10px 0px 10px 0px;
+}
+
+.toggleList dt span {
+ font-family: monospace;
+ padding:0;
+ margin:0;
+}
+
+
+.toggleList dd {
+ margin:0;
+ padding:0;
+}
+
+html.isjs .toggleList dd {
+ display: none;
+}
+
+.toggleList pre {
+ padding: 4px 4px 4px 4px;
+}
+
+
+
+
+
+/* COLORS */
+
+pre, code {
+ color: #000000;
+}
+
+
+body {
+ color : #333333;
+ background-color :#FFFFFF;
+}
+
+
+h1, h2, h3, h4, h5, h6 {
+ color:#555;
+}
+
+a,
+.toggleList dt {
+ color: #1a7eb0;
+}
+
+a:hover,
+a:active {
+ color: #1a7eb0;
+}
+
+a:visited,
+a:link:visited {
+ color: #1a7eb0;
+}
+
+td,tr {
+ border-color: #999999;
+}
+
+hr {
+ color:#999999;
+ background:#999999;
+}
+
+
+.TableHeadingColor {
+ background: #dcdcdc;
+ color: #555;
+}
+
+
+.TableSubHeadingColor {
+ background: #EEEEFF
+}
+
+.TableRowColor {
+ background: #FFFFFF
+}
+
+
+.NavBarCell1 {
+ background-color:#dcdcdc;
+ color:#000;
+}
+
+.NavBarCell1 a {
+ color:#333;
+}
+
+
+.NavBarCell1Rev {
+ background-color:transparent;
+}
+
+.NavBarFont1 {
+ color:#333;
+}
+
+
+.NavBarFont1Rev {
+ color:#fff;
+}
+
+.NavBarCell2 {
+ background-color:#999;
+}
+
+.NavBarCell2 a {
+ color:#fff;
+}
+
+
+
+.NavBarCell3 {
+ background-color:#dcdcdc;
+}
+
View
193 src/peasy/PeasyCam.java
@@ -0,0 +1,193 @@
+/*
+ The PeasyCam Processing library, which provides an easy-peasy
+ camera for 3D sketching.
+
+ Copyright 2008 Jonathan Feinberg
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+ */
+package peasy;
+
+import java.awt.event.MouseEvent;
+
+import peasy.org.apache.commons.math.geometry.Rotation;
+import peasy.org.apache.commons.math.geometry.Vector3D;
+import processing.core.PApplet;
+import processing.core.PConstants;
+
+/**
+ * @author Jonathan Feinberg
+ */
+public class PeasyCam
+{
+ private static final Vector3D LOOK = Vector3D.minusK;
+ private static final Vector3D UP = Vector3D.minusJ;
+
+ final PApplet p;
+
+ final double startDistance;
+ final Vector3D startCenter;
+
+ PeasyMouseListener mouseListener = null;
+
+ double distance;
+ Vector3D center;
+ Rotation rotation;
+
+ public final String VERSION = "0.1.0";
+
+ public PeasyCam(final PApplet parent, final double distance)
+ {
+ this(parent, 0, 0, 0, distance);
+ }
+
+ public PeasyCam(final PApplet parent, final double lookAtX, final double lookAtY,
+ final double lookAtZ, final double distance)
+ {
+ this.p = parent;
+ this.startCenter = this.center = new Vector3D(lookAtX, lookAtY, lookAtZ);
+ this.startDistance = this.distance = distance;
+ this.rotation = new Rotation();
+ setMouseControlled(true);
+ feed();
+ }
+
+ public void setMouseControlled(final boolean isMouseControlled)
+ {
+ if (isMouseControlled)
+ {
+ if (mouseListener != null)
+ {
+ PApplet.println("PeasyCam is already listening to mouse.");
+ return;
+ }
+ p.registerMouseEvent(mouseListener = new PeasyMouseListener());
+ }
+ else
+ {
+ if (mouseListener == null)
+ {
+ PApplet.println("PeasyCam is not listening to mouse.");
+ return;
+ }
+ p.unregisterMouseEvent(mouseListener);
+ mouseListener = null;
+ }
+ }
+
+ public String version()
+ {
+ return VERSION;
+ }
+
+ protected class PeasyMouseListener
+ {
+ public void mouseEvent(final MouseEvent e)
+ {
+ if (e.getID() == MouseEvent.MOUSE_CLICKED && e.getClickCount() == 2)
+ {
+ reset();
+
+ }
+ else if (e.getID() == MouseEvent.MOUSE_DRAGGED)
+ {
+ float dx = p.mouseX - p.pmouseX;
+ float dy = p.mouseY - p.pmouseY;
+ if (p.mouseButton == PConstants.LEFT)
+ mouseRotate(dx, dy);
+ else if (p.mouseButton == PConstants.RIGHT)
+ mouseZoom(dy);
+ else
+ mousePan(dx, dy);
+ }
+ }
+
+ public void reset()
+ {
+ center = startCenter;
+ distance = startDistance;
+ rotation = new Rotation();
+ feed();
+ }
+
+ private void mouseZoom(final double delta)
+ {
+ setDistance(distance + delta * Math.sqrt(distance * .2));
+ }
+
+ private void mousePan(final float dxMouse, final float dyMouse)
+ {
+ final double panScale = Math.sqrt(distance * .005);
+ pan(-dxMouse * panScale, dyMouse * panScale);
+ }
+
+ private void mouseRotate(final float dx, final float dy)
+ {
+ final Vector3D u = LOOK.scalarMultiply(distance).negate();
+ final double rotationScale = Math.sqrt(distance * .05);
+
+ final Vector3D vx = u.add(new Vector3D(dx * rotationScale, 0, 0));
+ rotateY(Vector3D.angle(u, vx) * (dx < 0 ? -1 : 1));
+
+ final Vector3D vy = u.add(new Vector3D(0, dy * rotationScale, 0));
+ final double yAngle = Vector3D.angle(u, vy) * (dy < 0 ? -1 : 1);
+ rotateX(yAngle);
+ }
+ }
+
+ public void lookAt(final double x, final double y, final double z)
+ {
+ center = new Vector3D(x, y, z);
+ }
+
+ public void setDistance(final double distance)
+ {
+ this.distance = distance;
+ if (this.distance < .01)
+ this.distance = .01;
+ feed();
+ }
+
+ public void feed()
+ {
+ final Vector3D pos = rotation.applyTo(LOOK).scalarMultiply(distance).add(center);
+ final Vector3D rup = rotation.applyTo(UP);
+ p.camera((float) pos.getX(), (float) pos.getY(), (float) pos.getZ(),
+ (float) center.getX(), (float) center.getY(), (float) center.getZ(),
+ (float) rup.getX(), (float) rup.getY(), (float) rup.getZ());
+ }
+
+ public void pan(final double dx, final double dy)
+ {
+ center = center.add(rotation.applyTo(new Vector3D(dx, dy, 0)));
+ feed();
+ }
+
+ public void rotateX(final double yAngle)
+ {
+ rotation = rotation.applyTo(new Rotation(Vector3D.plusI, yAngle));
+ feed();
+ }
+
+ public void rotateY(final double angle)
+ {
+ rotation = rotation.applyTo(new Rotation(Vector3D.plusJ, angle));
+ feed();
+ }
+
+ public void rotateZ(final double angle)
+ {
+ rotation = rotation.applyTo(new Rotation(Vector3D.plusK, angle));
+ feed();
+ }
+}
View
279 src/peasy/org/apache/commons/math/MathException.java
@@ -0,0 +1,279 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package peasy.org.apache.commons.math;
+
+import java.io.PrintStream;
+import java.io.PrintWriter;
+import java.text.MessageFormat;
+import java.util.Locale;
+import java.util.MissingResourceException;
+import java.util.ResourceBundle;
+
+
+/**
+* Base class for commons-math checked exceptions.
+* <p>
+* Supports nesting, emulating JDK 1.4 behavior if necessary.</p>
+* <p>
+* Adapted from {@link org.apache.commons.collections.FunctorException}.</p>
+*
+* @version $Revision: 620312 $ $Date: 2008-02-10 12:28:59 -0700 (Sun, 10 Feb 2008) $
+*/
+public class MathException extends Exception {
+
+ /** Serializable version identifier */
+ private static final long serialVersionUID = -8602234299177097102L;
+
+ /**
+ * Does JDK support nested exceptions?
+ */
+ private static final boolean JDK_SUPPORTS_NESTED;
+
+ static {
+ boolean flag = false;
+ try {
+ Throwable.class.getDeclaredMethod("getCause", new Class[0]);
+ flag = true;
+ } catch (NoSuchMethodException ex) {
+ flag = false;
+ }
+ JDK_SUPPORTS_NESTED = flag;
+ }
+
+ /** Cache for resources bundle. */
+ private static ResourceBundle cachedResources = null;
+
+ /**
+ * Pattern used to build the message.
+ */
+ private final String pattern;
+
+ /**
+ * Arguments used to build the message.
+ */
+ private final Object[] arguments;
+
+ /**
+ * Root cause of the exception
+ */
+ private final Throwable rootCause;
+
+ /**
+ * Translate a string to a given locale.
+ * @param s string to translate
+ * @param locale locale into which to translate the string
+ * @return translated string or original string
+ * for unsupported locales or unknown strings
+ */
+ private static String translate(String s, Locale locale) {
+ try {
+ if ((cachedResources == null) || (! cachedResources.getLocale().equals(locale))) {
+ // caching the resource bundle
+ cachedResources =
+ ResourceBundle.getBundle("peasy.org.apache.commons.math.MessagesResources", locale);
+ }
+
+ if (cachedResources.getLocale().getLanguage().equals(locale.getLanguage())) {
+ // the value of the resource is the translated string
+ return cachedResources.getString(s);
+ }
+
+ } catch (MissingResourceException mre) {
+ // do nothing here
+ }
+
+ // the locale is not supported or the resource is unknown
+ // don't translate and fall back to using the string as is
+ return s;
+
+ }
+
+ /**
+ * Builds a message string by from a pattern and its arguments.
+ * @param pattern format specifier
+ * @param arguments format arguments
+ * @param locale Locale in which the message should be translated
+ * @return a message string
+ */
+ private static String buildMessage(String pattern, Object[] arguments, Locale locale) {
+ // do it the hard way, for Java 1.3. compatibility
+ MessageFormat mf = new MessageFormat(translate(pattern, locale));
+ mf.setLocale(locale);
+ return mf.format(arguments);
+ }
+
+ /**
+ * Constructs a new <code>MathException</code> with no
+ * detail message.
+ */
+ public MathException() {
+ super();
+ this.pattern = null;
+ this.arguments = new Object[0];
+ this.rootCause = null;
+ }
+
+ /**
+ * Constructs a new <code>MathException</code> with specified
+ * detail message.
+ *
+ * @param msg the error message.
+ * @deprecated as of 1.2, replaced by {@link #MathException(String, Object[])}
+ */
+ public MathException(String msg) {
+ super(msg);
+ this.pattern = msg;
+ this.arguments = new Object[0];
+ this.rootCause = null;
+ }
+
+ /**
+ * Constructs a new <code>MathException</code> with specified
+ * formatted detail message.
+ * Message formatting is delegated to {@link java.text.MessageFormat}.
+ * @param pattern format specifier
+ * @param arguments format arguments
+ */
+ public MathException(String pattern, Object[] arguments) {
+ super(buildMessage(pattern, arguments, Locale.US));
+ this.pattern = pattern;
+ this.arguments = (Object[]) arguments.clone();
+ this.rootCause = null;
+ }
+
+ /**
+ * Constructs a new <code>MathException</code> with specified
+ * nested <code>Throwable</code> root cause.
+ *
+ * @param rootCause the exception or error that caused this exception
+ * to be thrown.
+ */
+ public MathException(Throwable rootCause) {
+ super((rootCause == null ? null : rootCause.getMessage()));
+ this.pattern = getMessage();
+ this.arguments = new Object[0];
+ this.rootCause = rootCause;
+ }
+
+ /**
+ * Constructs a new <code>MathException</code> with specified
+ * detail message and nested <code>Throwable</code> root cause.
+ *
+ * @param msg the error message.
+ * @param rootCause the exception or error that caused this exception
+ * to be thrown.
+ * @deprecated as of 1.2, replaced by {@link #MathException(String, Object[], Throwable)}
+ */
+ public MathException(String msg, Throwable rootCause) {
+ super(msg);
+ this.pattern = msg;
+ this.arguments = new Object[0];
+ this.rootCause = rootCause;
+ }
+
+ /**
+ * Constructs a new <code>MathException</code> with specified
+ * formatted detail message and nested <code>Throwable</code> root cause.
+ * Message formatting is delegated to {@link java.text.MessageFormat}.
+ * @param pattern format specifier
+ * @param arguments format arguments
+ * @param rootCause the exception or error that caused this exception
+ * to be thrown.
+ * @since 1.2
+ */
+ public MathException(String pattern, Object[] arguments, Throwable rootCause) {
+ super(buildMessage(pattern, arguments, Locale.US));
+ this.pattern = pattern;
+ this.arguments = (Object[]) arguments.clone();
+ this.rootCause = rootCause;
+ }
+
+ /** Gets the pattern used to build the message of this throwable.
+ *
+ * @return the pattern used to build the message of this throwable
+ * @since 1.2
+ */
+ public String getPattern() {
+ return pattern;
+ }
+
+ /** Gets the arguments used to build the message of this throwable.
+ *
+ * @return the arguments used to build the message of this throwable
+ * @since 1.2
+ */
+ public Object[] getArguments() {
+ return (Object[]) arguments.clone();
+ }
+
+ /** Gets the message in a specified locale.
+ *
+ * @param locale Locale in which the message should be translated
+ *
+ * @return localized message
+ * @since 1.2
+ */
+ public String getMessage(Locale locale) {
+ return (pattern == null) ? null : buildMessage(pattern, arguments, locale);
+ }
+
+ /**
+ * Gets the cause of this throwable.
+ *
+ * @return the cause of this throwable, or <code>null</code>
+ */
+ public Throwable getCause() {
+ return rootCause;
+ }
+
+ /**
+ * Prints the stack trace of this exception to the standard error stream.
+ */
+ public void printStackTrace() {
+ printStackTrace(System.err);
+ }
+
+ /**
+ * Prints the stack trace of this exception to the specified stream.
+ *
+ * @param out the <code>PrintStream</code> to use for output
+ */
+ public void printStackTrace(PrintStream out) {
+ synchronized (out) {
+ PrintWriter pw = new PrintWriter(out, false);
+ printStackTrace(pw);
+ // Flush the PrintWriter before it's GC'ed.
+ pw.flush();
+ }
+ }
+
+ /**
+ * Prints the stack trace of this exception to the specified writer.
+ *
+ * @param out the <code>PrintWriter</code> to use for output
+ */
+ public void printStackTrace(PrintWriter out) {
+ synchronized (out) {
+ super.printStackTrace(out);
+ if (rootCause != null && JDK_SUPPORTS_NESTED == false) {
+ out.print("Caused by: ");
+ rootCause.printStackTrace(out);
+ }
+ }
+ }
+
+}
View
44 src/peasy/org/apache/commons/math/geometry/CardanEulerSingularityException.java
@@ -0,0 +1,44 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package peasy.org.apache.commons.math.geometry;
+
+import peasy.org.apache.commons.math.MathException;
+
+/** This class represents exceptions thrown while extractiong Cardan
+ * or Euler angles from a rotation.
+
+ * @version $Revision: 620312 $ $Date: 2008-02-10 12:28:59 -0700 (Sun, 10 Feb 2008) $
+ * @since 1.2
+ */
+public class CardanEulerSingularityException
+ extends MathException {
+
+ /**
+ * Simple constructor.
+ * build an exception with a default message.
+ * @param isCardan if true, the rotation is related to Cardan angles,
+ * if false it is related to EulerAngles
+ */
+ public CardanEulerSingularityException(boolean isCardan) {
+ super(isCardan ? "Cardan angles singularity" : "Euler angles singularity", new Object[0]);
+ }
+
+ /** Serializable version identifier */
+ private static final long serialVersionUID = -1360952845582206770L;
+
+}
View
46 src/peasy/org/apache/commons/math/geometry/NotARotationMatrixException.java
@@ -0,0 +1,46 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package peasy.org.apache.commons.math.geometry;
+
+import peasy.org.apache.commons.math.MathException;
+
+/**
+ * This class represents exceptions thrown while building rotations
+ * from matrices.
+ *
+ * @version $Revision: 627994 $ $Date: 2008-02-15 03:16:05 -0700 (Fri, 15 Feb 2008) $
+ * @since 1.2
+ */
+
+public class NotARotationMatrixException
+ extends MathException {
+
+ /**
+ * Simple constructor.
+ * Build an exception by translating and formating a message
+ * @param specifier format specifier (to be translated)
+ * @param parts to insert in the format (no translation)
+ */
+ public NotARotationMatrixException(String specifier, Object[] parts) {
+ super(specifier, parts);
+ }
+
+ /** Serializable version identifier */
+ private static final long serialVersionUID = 5647178478658937642L;
+
+}
View
1,035 src/peasy/org/apache/commons/math/geometry/Rotation.java
@@ -0,0 +1,1035 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package peasy.org.apache.commons.math.geometry;
+
+import java.io.Serializable;
+
+/**
+ * This class implements rotations in a three-dimensional space.
+ *
+ * <p>Rotations can be represented by several different mathematical
+ * entities (matrices, axe and angle, Cardan or Euler angles,
+ * quaternions). This class presents an higher level abstraction, more
+ * user-oriented and hiding this implementation details. Well, for the
+ * curious, we use quaternions for the internal representation. The
+ * user can build a rotation from any of these representations, and
+ * any of these representations can be retrieved from a
+ * <code>Rotation</code> instance (see the various constructors and
+ * getters). In addition, a rotation can also be built implicitely
+ * from a set of vectors and their image.</p>
+ * <p>This implies that this class can be used to convert from one
+ * representation to another one. For example, converting a rotation
+ * matrix into a set of Cardan angles from can be done using the
+ * followong single line of code:</p>
+ * <pre>
+ * double[] angles = new Rotation(matrix, 1.0e-10).getAngles(RotationOrder.XYZ);
+ * </pre>
+ * <p>Focus is oriented on what a rotation <em>do</em> rather than on its
+ * underlying representation. Once it has been built, and regardless of its
+ * internal representation, a rotation is an <em>operator</em> which basically
+ * transforms three dimensional {@link Vector3D vectors} into other three
+ * dimensional {@link Vector3D vectors}. Depending on the application, the
+ * meaning of these vectors may vary and the semantics of the rotation also.</p>
+ * <p>For example in an spacecraft attitude simulation tool, users will often
+ * consider the vectors are fixed (say the Earth direction for example) and the
+ * rotation transforms the coordinates coordinates of this vector in inertial
+ * frame into the coordinates of the same vector in satellite frame. In this
+ * case, the rotation implicitely defines the relation between the two frames.
+ * Another example could be a telescope control application, where the rotation
+ * would transform the sighting direction at rest into the desired observing
+ * direction when the telescope is pointed towards an object of interest. In this
+ * case the rotation transforms the directionf at rest in a topocentric frame
+ * into the sighting direction in the same topocentric frame. In many case, both
+ * approaches will be combined, in our telescope example, we will probably also
+ * need to transform the observing direction in the topocentric frame into the
+ * observing direction in inertial frame taking into account the observatory
+ * location and the Earth rotation.</p>
+ *
+ * <p>These examples show that a rotation is what the user wants it to be, so this
+ * class does not push the user towards one specific definition and hence does not
+ * provide methods like <code>projectVectorIntoDestinationFrame</code> or
+ * <code>computeTransformedDirection</code>. It provides simpler and more generic
+ * methods: {@link #applyTo(Vector3D) applyTo(Vector3D)} and {@link
+ * #applyInverseTo(Vector3D) applyInverseTo(Vector3D)}.</p>
+ *
+ * <p>Since a rotation is basically a vectorial operator, several rotations can be
+ * composed together and the composite operation <code>r = r<sub>1</sub> o
+ * r<sub>2</sub></code> (which means that for each vector <code>u</code>,
+ * <code>r(u) = r<sub>1</sub>(r<sub>2</sub>(u))</code>) is also a rotation. Hence
+ * we can consider that in addition to vectors, a rotation can be applied to other
+ * rotations as well (or to itself). With our previous notations, we would say we
+ * can apply <code>r<sub>1</sub></code> to <code>r<sub>2</sub></code> and the result
+ * we get is <code>r = r<sub>1</sub> o r<sub>2</sub></code>. For this purpose, the
+ * class provides the methods: {@link #applyTo(Rotation) applyTo(Rotation)} and
+ * {@link #applyInverseTo(Rotation) applyInverseTo(Rotation)}.</p>
+ *
+ * <p>Rotations are guaranteed to be immutable objects.</p>
+ *
+ * @version $Revision: 627994 $ $Date: 2008-02-15 03:16:05 -0700 (Fri, 15 Feb 2008) $
+ * @see Vector3D
+ * @see RotationOrder
+ * @since 1.2
+ */
+
+public class Rotation implements Serializable {
+
+ /** Build the identity rotation.
+ */
+ public Rotation() {
+ q0 = 1;
+ q1 = 0;
+ q2 = 0;
+ q3 = 0;
+ }
+
+ /** Build a rotation from the quaternion coordinates.
+ * <p>A rotation can be built from a <em>normalized</em> quaternion,
+ * i.e. a quaternion for which q<sub>0</sub><sup>2</sup> +
+ * q<sub>1</sub><sup>2</sup> + q<sub>2</sub><sup>2</sup> +
+ * q<sub>3</sub><sup>2</sup> = 1. If the quaternion is not normalized,
+ * the constructor can normalize it in a preprocessing step.</p>
+ * @param q0 scalar part of the quaternion
+ * @param q1 first coordinate of the vectorial part of the quaternion
+ * @param q2 second coordinate of the vectorial part of the quaternion
+ * @param q3 third coordinate of the vectorial part of the quaternion
+ * @param needsNormalization if true, the coordinates are considered
+ * not to be normalized, a normalization preprocessing step is performed
+ * before using them
+ */
+ public Rotation(double q0, double q1, double q2, double q3,
+ boolean needsNormalization) {
+
+ if (needsNormalization) {
+ // normalization preprocessing
+ double inv = 1.0 / Math.sqrt(q0 * q0 + q1 * q1 + q2 * q2 + q3 * q3);
+ q0 *= inv;
+ q1 *= inv;
+ q2 *= inv;
+ q3 *= inv;
+ }
+
+ this.q0 = q0;
+ this.q1 = q1;
+ this.q2 = q2;
+ this.q3 = q3;
+
+ }
+
+ /** Build a rotation from an axis and an angle.
+ * <p>We use the convention that angles are oriented according to
+ * the effect of the rotation on vectors around the axis. That means
+ * that if (i, j, k) is a direct frame and if we first provide +k as
+ * the axis and PI/2 as the angle to this constructor, and then
+ * {@link #applyTo(Vector3D) apply} the instance to +i, we will get
+ * +j.</p>
+ * @param axis axis around which to rotate
+ * @param angle rotation angle.
+ * @exception ArithmeticException if the axis norm is zero
+ */
+ public Rotation(Vector3D axis, double angle) {
+
+ double norm = axis.getNorm();
+ if (norm == 0) {
+ throw new ArithmeticException("zero norm for rotation axis");
+ }
+
+ double halfAngle = -0.5 * angle;
+ double coeff = Math.sin(halfAngle) / norm;
+
+ q0 = Math.cos (halfAngle);
+ q1 = coeff * axis.getX();
+ q2 = coeff * axis.getY();
+ q3 = coeff * axis.getZ();
+
+ }
+
+ /** Build a rotation from a 3X3 matrix.
+
+ * <p>Rotation matrices are orthogonal matrices, i.e. unit matrices
+ * (which are matrices for which m.m<sup>T</sup> = I) with real
+ * coefficients. The module of the determinant of unit matrices is
+ * 1, among the orthogonal 3X3 matrices, only the ones having a
+ * positive determinant (+1) are rotation matrices.</p>
+
+ * <p>When a rotation is defined by a matrix with truncated values
+ * (typically when it is extracted from a technical sheet where only
+ * four to five significant digits are available), the matrix is not
+ * orthogonal anymore. This constructor handles this case
+ * transparently by using a copy of the given matrix and applying a
+ * correction to the copy in order to perfect its orthogonality. If
+ * the Frobenius norm of the correction needed is above the given
+ * threshold, then the matrix is considered to be too far from a
+ * true rotation matrix and an exception is thrown.<p>
+
+ * @param m rotation matrix
+ * @param threshold convergence threshold for the iterative
+ * orthogonality correction (convergence is reached when the
+ * difference between two steps of the Frobenius norm of the
+ * correction is below this threshold)
+
+ * @exception NotARotationMatrixException if the matrix is not a 3X3
+ * matrix, or if it cannot be transformed into an orthogonal matrix
+ * with the given threshold, or if the determinant of the resulting
+ * orthogonal matrix is negative
+
+ */
+ public Rotation(double[][] m, double threshold)
+ throws NotARotationMatrixException {
+
+ // dimension check
+ if ((m.length != 3) || (m[0].length != 3) ||
+ (m[1].length != 3) || (m[2].length != 3)) {
+ throw new NotARotationMatrixException("a {0}x{1} matrix" +
+ " cannot be a rotation matrix",
+ new Object[] {
+ Integer.toString(m.length),
+ Integer.toString(m[0].length)
+ });
+ }
+
+ // compute a "close" orthogonal matrix
+ double[][] ort = orthogonalizeMatrix(m, threshold);
+
+ // check the sign of the determinant
+ double det = ort[0][0] * (ort[1][1] * ort[2][2] - ort[2][1] * ort[1][2]) -
+ ort[1][0] * (ort[0][1] * ort[2][2] - ort[2][1] * ort[0][2]) +
+ ort[2][0] * (ort[0][1] * ort[1][2] - ort[1][1] * ort[0][2]);
+ if (det < 0.0) {
+ throw new NotARotationMatrixException("the closest orthogonal matrix" +
+ " has a negative determinant {0}",
+ new Object[] {
+ Double.toString(det)
+ });
+ }
+
+ // There are different ways to compute the quaternions elements
+ // from the matrix. They all involve computing one element from
+ // the diagonal of the matrix, and computing the three other ones
+ // using a formula involving a division by the first element,
+ // which unfortunately can be zero. Since the norm of the
+ // quaternion is 1, we know at least one element has an absolute
+ // value greater or equal to 0.5, so it is always possible to
+ // select the right formula and avoid division by zero and even
+ // numerical inaccuracy. Checking the elements in turn and using
+ // the first one greater than 0.45 is safe (this leads to a simple
+ // test since qi = 0.45 implies 4 qi^2 - 1 = -0.19)
+ double s = ort[0][0] + ort[1][1] + ort[2][2];
+ if (s > -0.19) {
+ // compute q0 and deduce q1, q2 and q3
+ q0 = 0.5 * Math.sqrt(s + 1.0);
+ double inv = 0.25 / q0;
+ q1 = inv * (ort[1][2] - ort[2][1]);
+ q2 = inv * (ort[2][0] - ort[0][2]);
+ q3 = inv * (ort[0][1] - ort[1][0]);
+ } else {
+ s = ort[0][0] - ort[1][1] - ort[2][2];
+ if (s > -0.19) {
+ // compute q1 and deduce q0, q2 and q3
+ q1 = 0.5 * Math.sqrt(s + 1.0);
+ double inv = 0.25 / q1;
+ q0 = inv * (ort[1][2] - ort[2][1]);
+ q2 = inv * (ort[0][1] + ort[1][0]);
+ q3 = inv * (ort[0][2] + ort[2][0]);
+ } else {
+ s = ort[1][1] - ort[0][0] - ort[2][2];
+ if (s > -0.19) {
+ // compute q2 and deduce q0, q1 and q3
+ q2 = 0.5 * Math.sqrt(s + 1.0);
+ double inv = 0.25 / q2;
+ q0 = inv * (ort[2][0] - ort[0][2]);
+ q1 = inv * (ort[0][1] + ort[1][0]);
+ q3 = inv * (ort[2][1] + ort[1][2]);
+ } else {
+ // compute q3 and deduce q0, q1 and q2
+ s = ort[2][2] - ort[0][0] - ort[1][1];
+ q3 = 0.5 * Math.sqrt(s + 1.0);
+ double inv = 0.25 / q3;
+ q0 = inv * (ort[0][1] - ort[1][0]);
+ q1 = inv * (ort[0][2] + ort[2][0]);
+ q2 = inv * (ort[2][1] + ort[1][2]);
+ }
+ }
+ }
+
+ }
+
+ /** Build the rotation that transforms a pair of vector into another pair.
+
+ * <p>Except for possible scale factors, if the instance were applied to
+ * the pair (u<sub>1</sub>, u<sub>2</sub>) it will produce the pair
+ * (v<sub>1</sub>, v<sub>2</sub>).</p>
+
+ * <p>If the angular separation between u<sub>1</sub> and u<sub>2</sub> is
+ * not the same as the angular separation between v<sub>1</sub> and
+ * v<sub>2</sub>, then a corrected v'<sub>2</sub> will be used rather than
+ * v<sub>2</sub>, the corrected vector will be in the (v<sub>1</sub>,
+ * v<sub>2</sub>) plane.</p>
+
+ * @param u1 first vector of the origin pair
+ * @param u2 second vector of the origin pair
+ * @param v1 desired image of u1 by the rotation
+ * @param v2 desired image of u2 by the rotation
+ * @exception IllegalArgumentException if the norm of one of the vectors is zero
+ */
+ public Rotation(Vector3D u1, Vector3D u2, Vector3D v1, Vector3D v2) {
+
+ // norms computation
+ double u1u1 = Vector3D.dotProduct(u1, u1);
+ double u2u2 = Vector3D.dotProduct(u2, u2);
+ double v1v1 = Vector3D.dotProduct(v1, v1);
+ double v2v2 = Vector3D.dotProduct(v2, v2);
+ if ((u1u1 == 0) || (u2u2 == 0) || (v1v1 == 0) || (v2v2 == 0)) {
+ throw new IllegalArgumentException("zero norm for rotation defining vector");
+ }
+
+ double u1x = u1.getX();
+ double u1y = u1.getY();
+ double u1z = u1.getZ();
+
+ double u2x = u2.getX();
+ double u2y = u2.getY();
+ double u2z = u2.getZ();
+
+ // normalize v1 in order to have (v1'|v1') = (u1|u1)
+ double coeff = Math.sqrt (u1u1 / v1v1);
+ double v1x = coeff * v1.getX();
+ double v1y = coeff * v1.getY();
+ double v1z = coeff * v1.getZ();
+ v1 = new Vector3D(v1x, v1y, v1z);
+
+ // adjust v2 in order to have (u1|u2) = (v1|v2) and (v2'|v2') = (u2|u2)
+ double u1u2 = Vector3D.dotProduct(u1, u2);
+ double v1v2 = Vector3D.dotProduct(v1, v2);
+ double coeffU = u1u2 / u1u1;
+ double coeffV = v1v2 / u1u1;
+ double beta = Math.sqrt((u2u2 - u1u2 * coeffU) / (v2v2 - v1v2 * coeffV));
+ double alpha = coeffU - beta * coeffV;
+ double v2x = alpha * v1x + beta * v2.getX();
+ double v2y = alpha * v1y + beta * v2.getY();
+ double v2z = alpha * v1z + beta * v2.getZ();
+ v2 = new Vector3D(v2x, v2y, v2z);
+
+ // preliminary computation (we use explicit formulation instead
+ // of relying on the Vector3D class in order to avoid building lots
+ // of temporary objects)
+ Vector3D uRef = u1;
+ Vector3D vRef = v1;
+ double dx1 = v1x - u1.getX();
+ double dy1 = v1y - u1.getY();
+ double dz1 = v1z - u1.getZ();
+ double dx2 = v2x - u2.getX();
+ double dy2 = v2y - u2.getY();
+ double dz2 = v2z - u2.getZ();
+ Vector3D k = new Vector3D(dy1 * dz2 - dz1 * dy2,
+ dz1 * dx2 - dx1 * dz2,
+ dx1 * dy2 - dy1 * dx2);
+ double c = k.getX() * (u1y * u2z - u1z * u2y) +
+ k.getY() * (u1z * u2x - u1x * u2z) +
+ k.getZ() * (u1x * u2y - u1y * u2x);
+
+ if (c == 0) {
+ // the (q1, q2, q3) vector is in the (u1, u2) plane
+ // we try other vectors
+ Vector3D u3 = Vector3D.crossProduct(u1, u2);
+ Vector3D v3 = Vector3D.crossProduct(v1, v2);
+ double u3x = u3.getX();
+ double u3y = u3.getY();
+ double u3z = u3.getZ();
+ double v3x = v3.getX();
+ double v3y = v3.getY();
+ double v3z = v3.getZ();
+
+ double dx3 = v3x - u3x;
+ double dy3 = v3y - u3y;
+ double dz3 = v3z - u3z;
+ k = new Vector3D(dy1 * dz3 - dz1 * dy3,
+ dz1 * dx3 - dx1 * dz3,
+ dx1 * dy3 - dy1 * dx3);
+ c = k.getX() * (u1y * u3z - u1z * u3y) +
+ k.getY() * (u1z * u3x - u1x * u3z) +
+ k.getZ() * (u1x * u3y - u1y * u3x);
+
+ if (c == 0) {
+ // the (q1, q2, q3) vector is aligned with u1:
+ // we try (u2, u3) and (v2, v3)
+ k = new Vector3D(dy2 * dz3 - dz2 * dy3,
+ dz2 * dx3 - dx2 * dz3,
+ dx2 * dy3 - dy2 * dx3);
+ c = k.getX() * (u2y * u3z - u2z * u3y) +
+ k.getY() * (u2z * u3x - u2x * u3z) +
+ k.getZ() * (u2x * u3y - u2y * u3x);
+
+ if (c == 0) {
+ // the (q1, q2, q3) vector is aligned with everything
+ // this is really the identity rotation
+ q0 = 1.0;
+ q1 = 0.0;
+ q2 = 0.0;
+ q3 = 0.0;
+ return;
+ }
+
+ // we will have to use u2 and v2 to compute the scalar part
+ uRef = u2;
+ vRef = v2;
+
+ }
+
+ }
+
+ // compute the vectorial part
+ c = Math.sqrt(c);
+ double inv = 1.0 / (c + c);
+ q1 = inv * k.getX();
+ q2 = inv * k.getY();
+ q3 = inv * k.getZ();
+
+ // compute the scalar part
+ k = new Vector3D(uRef.getY() * q3 - uRef.getZ() * q2,
+ uRef.getZ() * q1 - uRef.getX() * q3,
+ uRef.getX() * q2 - uRef.getY() * q1);
+ c = Vector3D.dotProduct(k, k);
+ q0 = Vector3D.dotProduct(vRef, k) / (c + c);
+
+ }
+
+ /** Build one of the rotations that transform one vector into another one.
+
+ * <p>Except for a possible scale factor, if the instance were
+ * applied to the vector u it will produce the vector v. There is an
+ * infinite number of such rotations, this constructor choose the
+ * one with the smallest associated angle (i.e. the one whose axis
+ * is orthogonal to the (u, v) plane). If u and v are colinear, an
+ * arbitrary rotation axis is chosen.</p>
+
+ * @param u origin vector
+ * @param v desired image of u by the rotation
+ * @exception IllegalArgumentException if the norm of one of the vectors is zero
+ */
+ public Rotation(Vector3D u, Vector3D v) {
+
+ double normProduct = u.getNorm() * v.getNorm();
+ if (normProduct == 0) {
+ throw new IllegalArgumentException("zero norm for rotation defining vector");
+ }
+
+ double dot = Vector3D.dotProduct(u, v);
+
+ if (dot < ((2.0e-15 - 1.0) * normProduct)) {
+ // special case u = -v: we select a PI angle rotation around
+ // an arbitrary vector orthogonal to u
+ Vector3D w = u.orthogonal();
+ q0 = 0.0;
+ q1 = -w.getX();
+ q2 = -w.getY();
+ q3 = -w.getZ();
+ } else {
+ // general case: (u, v) defines a plane, we select
+ // the shortest possible rotation: axis orthogonal to this plane
+ q0 = Math.sqrt(0.5 * (1.0 + dot / normProduct));
+ double coeff = 1.0 / (2.0 * q0 * normProduct);
+ q1 = coeff * (v.getY() * u.getZ() - v.getZ() * u.getY());
+ q2 = coeff * (v.getZ() * u.getX() - v.getX() * u.getZ());
+ q3 = coeff * (v.getX() * u.getY() - v.getY() * u.getX());
+ }
+
+ }
+
+ /** Build a rotation from three Cardan or Euler elementary rotations.
+
+ * <p>Cardan rotations are three successive rotations around the
+ * canonical axes X, Y and Z, each axis beeing used once. There are
+ * 6 such sets of rotations (XYZ, XZY, YXZ, YZX, ZXY and ZYX). Euler
+ * rotations are three successive rotations around the canonical
+ * axes X, Y and Z, the first and last rotations beeing around the
+ * same axis. There are 6 such sets of rotations (XYX, XZX, YXY,
+ * YZY, ZXZ and ZYZ), the most popular one being ZXZ.</p>
+ * <p>Beware that many people routinely use the term Euler angles even
+ * for what really are Cardan angles (this confusion is especially
+ * widespread in the aerospace business where Roll, Pitch and Yaw angles
+ * are often wrongly tagged as Euler angles).</p>
+
+ * @param order order of rotations to use
+ * @param alpha1 angle of the first elementary rotation
+ * @param alpha2 angle of the second elementary rotation
+ * @param alpha3 angle of the third elementary rotation
+ */
+ public Rotation(RotationOrder order,
+ double alpha1, double alpha2, double alpha3) {
+ Rotation r1 = new Rotation(order.getA1(), alpha1);
+ Rotation r2 = new Rotation(order.getA2(), alpha2);
+ Rotation r3 = new Rotation(order.getA3(), alpha3);
+ Rotation composed = r1.applyTo(r2.applyTo(r3));
+ q0 = composed.q0;
+ q1 = composed.q1;
+ q2 = composed.q2;
+ q3 = composed.q3;
+ }
+
+ /** Revert a rotation.
+ * Build a rotation which reverse the effect of another
+ * rotation. This means that if r(u) = v, then r.revert(v) = u. The
+ * instance is not changed.
+ * @return a new rotation whose effect is the reverse of the effect
+ * of the instance
+ */
+ public Rotation revert() {
+ return new Rotation(-q0, q1, q2, q3, false);
+ }
+
+ /** Get the scalar coordinate of the quaternion.
+ * @return scalar coordinate of the quaternion
+ */
+ public double getQ0() {
+ return q0;
+ }
+
+ /** Get the first coordinate of the vectorial part of the quaternion.
+ * @return first coordinate of the vectorial part of the quaternion
+ */
+ public double getQ1() {
+ return q1;
+ }
+
+ /** Get the second coordinate of the vectorial part of the quaternion.
+ * @return second coordinate of the vectorial part of the quaternion
+ */
+ public double getQ2() {
+ return q2;
+ }
+
+ /** Get the third coordinate of the vectorial part of the quaternion.
+ * @return third coordinate of the vectorial part of the quaternion
+ */
+ public double getQ3() {
+ return q3;
+ }
+
+ /** Get the normalized axis of the rotation.
+ * @return normalized axis of the rotation
+ */
+ public Vector3D getAxis() {
+ double squaredSine = q1 * q1 + q2 * q2 + q3 * q3;
+ if (squaredSine == 0) {
+ return new Vector3D(1, 0, 0);
+ } else if (q0 < 0) {
+ double inverse = 1 / Math.sqrt(squaredSine);
+ return new Vector3D(q1 * inverse, q2 * inverse, q3 * inverse);
+ }
+ double inverse = -1 / Math.sqrt(squaredSine);
+ return new Vector3D(q1 * inverse, q2 * inverse, q3 * inverse);