import math

import pytest

from pycivil.EXAGeometry.geometry import (
    Point3d,
    Vector3d,
    Vector3dApp,
    ForceCouple,
    ForceCoupleSystem
)


def test_vector3d_001():

    v1 = Vector3dApp(Point3d(1,2,3),4,5,6)
    assert v1.vx == 4
    assert v1.vy == 5
    assert v1.vz == 6
    assert Point3d(1,2,3) == v1.o

def test_force_couple_001():

    force = Vector3dApp(Point3d(0, 0, 0), (1, 1, 0))
    couple = Vector3d(0, 0, 10)

    fc = ForceCouple(force, couple)
    old_force = fc.force

    # I change origin from (0,0,0) to (1,0,0)
    fc.o = Point3d(1, 0, 0)

    # equal only if force and origin is equal
    #
    assert not fc.force == old_force

    assert fc.couple.vz == 9

def test_force_couple_002():

    force = Vector3dApp(Point3d(0.0, 0.0, 0.0), (1.0, 1.0, 0.0))
    assert force.vx == 1.0
    assert force.vy == 1.0
    assert force.vz == 0.0
    assert force.o.x == 0.0
    assert force.o.y == 0.0
    assert force.o.z == 0.0

    couple = Vector3d(0.0, 0.0, 0.0)

    force_couple = ForceCouple(force, couple)

    old_force = force_couple.force

    force_couple.o = Point3d(-1.0, 1.0, 0.0)

    # This is false because origin change from (0, 0, 0) to (-1.0, 1.0, 0.0)
    assert not force_couple.force == old_force

    assert force.norm() * force.o.distanceFrom(force_couple.o) == pytest.approx(force_couple.couple.norm())

# Two parallel forces with same distance from (0, 0, 0) give a couple of null norm.
def test_force_couple_003():
    force1 = ForceCouple(Vector3dApp(Point3d( 0.0, -1.0, 0.0), (1.0, 1.0, 0.0)), Vector3d(0.0, 0.0, 0.0))
    force2 = ForceCouple(Vector3dApp(Point3d(-1.0,  0.0, 0.0), (1.0, 1.0, 0.0)), Vector3d(0.0, 0.0, 0.0))
    resultant = force1 + force2
    assert resultant.force.norm() == 2 * math.sqrt(2)
    resultant.o = Point3d( 0.0, 0.0, 0.0)
    assert resultant.couple.norm() == 0.0

def test_force_couple_system_001():
    force1 = ForceCouple(Vector3dApp(Point3d( 0.0, -1.0, 0.0), (1.0, 1.0, 0.0)), Vector3d(0.0, 0.0, 0.0))
    force2 = ForceCouple(Vector3dApp(Point3d(-1.0,  0.0, 0.0), (1.0, 1.0, 0.0)), Vector3d(0.0, 0.0, 0.0))
    system = ForceCoupleSystem([force1, force2])
    assert system.baryOfApplicationPoints() == Point3d(-0.5, -0.5)
    reduced = system.forceCoupleResume(Point3d(0,0,0))
    assert reduced.o == Point3d(0,0,0)
    assert reduced.couple == Vector3d(0, 0, 0)
    assert reduced.force == Vector3d(2, 2, 0)




