/// <summary> /// Obtiene el centro de la circunferencia que pasa por los 2 puntos, con el radio indicado. /// Dependiendo del criterio (leftRule), se interpreta el signo del radio: /// Si leftRule entonces el radio se multiplica por la normal a la izquierda (leftNormal) para obtener el centro de la /// circunferencia. /// Si rightRule (!leftRule) entonces el radio se multiplica por la normal a la derecha (rightNormal) para obtener el /// centro de la circunferencia. /// Clip utiliza un criterio rightRule. /// <p /> /// Criterio rightRule: /// <c><![CDATA[ /// _ _ /// _ / \c /// _/ O pf O /// _/ / / \ /// / _/ radio - _/ | /// / /| radio + <-- /| | /// | / --> / / /// / / / _/ /// |/ / _/ /// O pi O__/ /// \ _/ /// ]]></c> /// <![CDATA[ /// p1 a/2 pm a/2 p2 /// x---------+-------->x /// \ | / /// \ | / /// \ | / /// \ |b / /// \ | / r /// \ | / /// \ | / /// \ | / /// \|/ /// pc /// ]]> /// Teniendo como dato p1, p2 y r, tenemos que obtener el centro del circulo que pasa por /// p1 y p2, con radio r. /// Con el vector 1-2 obtenemos la distancia a. /// b es calculado mediante la fórmula b = raizcua(r * r + a/2 * a/2). /// Creamos un vector perpendicular al 1-2 a una distacion a/2 desde p1 y obtenemos /// el punto central de la circunferencia. /// Con este dato y conociendo el radio ya simplemente calculamos la esquina del rectangulo. /// Si el radio es positivo, avanza en sentido contrario a las agujas del reloj. /// Si el radio es negativo, avanza en sentido de las agujas del reloj. /// <![CDATA[ /// + p2 /// /|\ /// | /// /____ | ____\ /// \ \___ | ___/ / /// \__ | __/ /// \_ | _/ /// radio - \ | / radio + /// (giro \ | / (giro horario) /// antihorario) \|/ /// | /// + p1 /// ]]> /// </summary> /// <exception cref="CalculoImposibleException"> /// Indica que no se puede calcular el /// centro. /// </exception> public static Vec2d EvaluateCenter(Vec2d pt0, Vec2d pt1, double radius, bool leftRule) { // Vector direccion normalizado y longitud. Vec2d dir = pt1.Sub(pt0); double a = dir.Length; if (a.EpsilonEquals(0)) { throw new Exception("CalculoImposible: Puntos coincidentes."); } dir = dir.Div(a); // Punto medio. Vec2d pm = vecMath.Interpolate(pt0, pt1, 0.5); // Se tratan radios erroneos que no permitan generar un circunferencia. double v = radius * radius - a * a / 4; if (v.EpsilonEquals(0)) { return(pm); } if (v < 0) { throw new Exception("CalculoImposible: Radio erroneo."); } double b = SysMath.Sign(radius) * SysMath.Sqrt(v); Vec2d normal; if (leftRule) { // Vector normal a la izquierda. normal = vecMath.PerpLeft(dir); } else { // Vector normal a la derecha. normal = vecMath.PerpRight(dir); } Vec2d vectorm1 = normal.Mul(b); return(pm.Add(vectorm1)); }
public double CalcDistance() { double radio = System.Math.Abs(this.Circle.Radius); Vec2d diff = this.Point.Sub(this.Circle.Center); double len = diff.Length; if (this.Solid && (len < radio)) { this.ClosestPoint = this.Point; return(0); } if (len.EpsilonEquals(0)) { // Justo en el centro del circulo.. this.ClosestPoint = this.Circle.GetPosition(0); return(radio); } this.ClosestPoint = this.Circle.Center.Add(diff.Div(len).Mul(radio)); return(System.Math.Abs(len - radio)); }