/*
GeoGebra - Dynamic Mathematics for Everyone
http://www.geogebra.org
This file is part of GeoGebra.
This program is free software; you can redistribute it and/or modify it
under the terms of the GNU General Public License as published by
the Free Software Foundation.
*/
/*
* AlgoAnglePoints.java
*
* Created on 30. August 2001, 21:37
*/
package org.geogebra.common.geogebra3D.kernel3D.algos;
import org.geogebra.common.geogebra3D.kernel3D.geos.GeoAngle3D;
import org.geogebra.common.kernel.Construction;
import org.geogebra.common.kernel.Kernel;
import org.geogebra.common.kernel.Matrix.Coords;
import org.geogebra.common.kernel.algos.AlgoAnglePointsND;
import org.geogebra.common.kernel.geos.GeoAngle;
import org.geogebra.common.kernel.kernelND.GeoDirectionND;
import org.geogebra.common.kernel.kernelND.GeoPointND;
/**
*
* @author mathieu
*/
public class AlgoAnglePoints3D extends AlgoAnglePointsND {
AlgoAnglePoints3D(Construction cons, String label, GeoPointND A,
GeoPointND B, GeoPointND C) {
this(cons, label, A, B, C, null);
}
AlgoAnglePoints3D(Construction cons, String label, GeoPointND A,
GeoPointND B, GeoPointND C, GeoDirectionND orientation) {
super(cons, label, A, B, C, orientation);
}
AlgoAnglePoints3D(Construction cons) {
super(cons);
}
@Override
protected GeoAngle newGeoAngle(Construction cons1) {
GeoAngle ret = new GeoAngle3D(cons);
ret.setDrawable(true);
return ret;
}
protected Coords center, v1, v2, vn;
@Override
public void compute() {
center = getB().getInhomCoordsInD3();
v1 = getA().getInhomCoordsInD3().sub(center);
v2 = getC().getInhomCoordsInD3().sub(center);
v1.calcNorm();
double l1 = v1.getNorm();
v2.calcNorm();
double l2 = v2.getNorm();
if (Kernel.isZero(l1) || Kernel.isZero(l2)) {
getAngle().setUndefined();
return;
}
double c = v1.dotproduct(v2) / (l1 * l2); // cosinus of the angle
getAngle().setValue(acos(c));
// normal vector
setForceNormalVector();
}
/**
* set normal vector (forced)
*/
protected void setForceNormalVector() {
vn = forceNormalVector(v1, v2);
}
@Override
public Coords getVn() {
return vn;
}
@Override
public boolean getCoordsInD3(Coords[] drawCoords) {
// v1 = getA().getInhomCoordsInD3().sub(center);
// v2 = getC().getInhomCoordsInD3().sub(center);
drawCoords[0].set(center);
drawCoords[1].set(v1);
drawCoords[2].set(v2);
return true;
}
/**
* acos, values can be a bit greater than 1 (or lower than 0)
*
* @param c
* cosinus of an angle
* @return angle between 0 and PI
*/
protected static final double acos(double c) {
// case where c is a bit more than 1
if (Kernel.isEqual(c, 1) && c > 1) {
return 0;
}
// case where c is a bit less than -1
if (Kernel.isEqual(c, -1) && c < -1) {
return Math.PI;
}
return Math.acos(c);
}
/**
* @param v1
* first vector
* @param v2
* second vector
* @return vector normal to v1, v2
*/
protected static final Coords forceNormalVector(Coords v1, Coords v2) {
Coords vn = v1.crossProduct4(v2);
if (vn.isZero()) { // v1 and v2 are dependent
vn = crossXorY(v1);
}
vn.normalize();
return vn;
}
/**
*
* @param v1
* vector
* @return non zero vector orthogonal to v1 and Ox or Oy
*/
protected static final Coords crossXorY(Coords v1) {
Coords vn = v1.crossProduct4(Coords.VX);
if (vn.isZero()) {
vn = v1.crossProduct4(Coords.VY);
}
return vn;
}
private AlgoAnglePoints3D(GeoPointND A, GeoPointND B, GeoPointND C,
Coords center, Coords v1, Coords v2, Coords vn) {
super(A, B, C);
this.center = center;
this.v1 = v1;
this.v2 = v2;
this.vn = vn;
}
@Override
public AlgoAnglePoints3D copy() {
return new AlgoAnglePoints3D(getA().copy(), getB().copy(),
getC().copy(), center.copyVector(), v1.copyVector(),
v2.copyVector(), vn.copyVector());
}
}