void MolfileLoader::_read3dFeature2000()

in core/indigo-core/molecule/src/molfile_loader.cpp [1574:1840]


void MolfileLoader::_read3dFeature2000()
{
    // read 3D feature ID (see MDL ctfile documentation)
    int feature_id = _scanner.readIntFix(3);

    _scanner.skipLine();

    Molecule3dConstraints* constraints = &_qmol->spatial_constraints;

    if (constraints->end() == 0)
        constraints->init();

    switch (feature_id)
    {
    case -1: // point defined by 2 points and distance
    {
        std::unique_ptr<Molecule3dConstraints::PointByDistance> constr = std::make_unique<Molecule3dConstraints::PointByDistance>();
        _scanner.skip(6);
        constr->beg_id = _scanner.readIntFix(3) - 1;
        constr->end_id = _scanner.readIntFix(3) - 1;
        constr->distance = _scanner.readFloatFix(10);
        _scanner.skipLine();

        constraints->add(constr.release());
        break;
    }
    case -2: // point defined by 2 points and percentage
    {
        std::unique_ptr<Molecule3dConstraints::PointByPercentage> constr = std::make_unique<Molecule3dConstraints::PointByPercentage>();
        _scanner.skip(6);
        constr->beg_id = _scanner.readIntFix(3) - 1;
        constr->end_id = _scanner.readIntFix(3) - 1;
        constr->percentage = _scanner.readFloatFix(10);
        _scanner.skipLine();

        constraints->add(constr.release());
        break;
    }
    case -3: // point defined by point, normal line, and distance
    {
        std::unique_ptr<Molecule3dConstraints::PointByNormale> constr = std::make_unique<Molecule3dConstraints::PointByNormale>();
        _scanner.skip(6);
        constr->org_id = _scanner.readIntFix(3) - 1;
        constr->norm_id = _scanner.readIntFix(3) - 1;
        constr->distance = _scanner.readFloatFix(10);
        _scanner.skipLine();

        constraints->add(constr.release());
        break;
    }
    case -4: // line defined by 2 or more points (best fit line if more than 2 points)
    {
        std::unique_ptr<Molecule3dConstraints::BestFitLine> constr = std::make_unique<Molecule3dConstraints::BestFitLine>();
        _scanner.skip(6);
        int amount = _scanner.readIntFix(3);
        if (amount < 2)
            throw Error("invalid points amount in M $3D-4 feature");

        constr->max_deviation = _scanner.readFloatFix(10);
        _scanner.skipLine();
        _scanner.skip(6);

        while (amount-- > 0)
            constr->point_ids.push(_scanner.readIntFix(3) - 1);

        _scanner.skipLine();
        constraints->add(constr.release());
        break;
    }
    case -5: // plane defined by 3 or more points (best fit line if more than 3 points)
    {
        std::unique_ptr<Molecule3dConstraints::BestFitPlane> constr = std::make_unique<Molecule3dConstraints::BestFitPlane>();
        _scanner.skip(6);

        int amount = _scanner.readIntFix(3);

        if (amount < 3)
            throw Error("invalid points amount in M $3D-5 feature");

        constr->max_deviation = _scanner.readFloatFix(10);
        _scanner.skipLine();
        _scanner.skip(6);

        while (amount-- > 0)
            constr->point_ids.push(_scanner.readIntFix(3) - 1);

        _scanner.skipLine();
        constraints->add(constr.release());
        break;
    }
    case -6: // plane defined by point and line
    {
        std::unique_ptr<Molecule3dConstraints::PlaneByPoint> constr = std::make_unique<Molecule3dConstraints::PlaneByPoint>();
        _scanner.skip(6);
        constr->point_id = _scanner.readIntFix(3) - 1;
        constr->line_id = _scanner.readIntFix(3) - 1;
        _scanner.skipLine();

        constraints->add(constr.release());
        break;
    }
    case -7: // centroid defined by points
    {
        std::unique_ptr<Molecule3dConstraints::Centroid> constr = std::make_unique<Molecule3dConstraints::Centroid>();
        _scanner.skip(6);

        int amount = _scanner.readIntFix(3);

        if (amount < 1)
            throw Error("invalid amount of points for centroid: %d", amount);

        _scanner.skipLine();
        _scanner.skip(6);

        while (amount-- > 0)
            constr->point_ids.push(_scanner.readIntFix(3) - 1);

        _scanner.skipLine();

        constraints->add(constr.release());
        break;
    }
    case -8: // normal line defined by point and plane
    {
        std::unique_ptr<Molecule3dConstraints::Normale> constr = std::make_unique<Molecule3dConstraints::Normale>();
        _scanner.skip(6);
        constr->point_id = _scanner.readIntFix(3) - 1;
        constr->plane_id = _scanner.readIntFix(3) - 1;

        _scanner.skipLine();

        constraints->add(constr.release());
        break;
    }
    case -9: // distance defined by 2 points and range
    {
        std::unique_ptr<Molecule3dConstraints::DistanceByPoints> constr = std::make_unique<Molecule3dConstraints::DistanceByPoints>();
        _scanner.skip(6);
        constr->beg_id = _scanner.readIntFix(3) - 1;
        constr->end_id = _scanner.readIntFix(3) - 1;
        constr->bottom = _scanner.readFloatFix(10);
        constr->top = _scanner.readFloatFix(10);
        _scanner.skipLine();

        constraints->add(constr.release());
        break;
    }
    case -10: // distance defined by point, line and range
    {
        std::unique_ptr<Molecule3dConstraints::DistanceByLine> constr = std::make_unique<Molecule3dConstraints::DistanceByLine>();
        _scanner.skip(6);
        constr->point_id = _scanner.readIntFix(3) - 1;
        constr->line_id = _scanner.readIntFix(3) - 1;
        constr->bottom = _scanner.readFloatFix(10);
        constr->top = _scanner.readFloatFix(10);
        _scanner.skipLine();

        constraints->add(constr.release());
        break;
    }
    case -11: // distance defined by point, plane and range
    {
        std::unique_ptr<Molecule3dConstraints::DistanceByPlane> constr = std::make_unique<Molecule3dConstraints::DistanceByPlane>();
        _scanner.skip(6);
        constr->point_id = _scanner.readIntFix(3) - 1;
        constr->plane_id = _scanner.readIntFix(3) - 1;
        constr->bottom = _scanner.readFloatFix(10);
        constr->top = _scanner.readFloatFix(10);
        _scanner.skipLine();

        constraints->add(constr.release());
        break;
    }
    case -12: // angle defined by 3 points and range
    {
        std::unique_ptr<Molecule3dConstraints::AngleByPoints> constr = std::make_unique<Molecule3dConstraints::AngleByPoints>();
        _scanner.skip(6);
        constr->point1_id = _scanner.readIntFix(3) - 1;
        constr->point2_id = _scanner.readIntFix(3) - 1;
        constr->point3_id = _scanner.readIntFix(3) - 1;
        constr->bottom = (float)(_scanner.readFloatFix(10) * M_PI / 180);
        constr->top = (float)(_scanner.readFloatFix(10) * M_PI / 180);
        _scanner.skipLine();
        constraints->add(constr.release());
        break;
    }
    case -13: // angle defined by 2 lines and range
    {
        std::unique_ptr<Molecule3dConstraints::AngleByLines> constr = std::make_unique<Molecule3dConstraints::AngleByLines>();
        _scanner.skip(6);
        constr->line1_id = _scanner.readIntFix(3) - 1;
        constr->line2_id = _scanner.readIntFix(3) - 1;
        constr->bottom = (float)(_scanner.readFloatFix(10) * M_PI / 180);
        constr->top = (float)(_scanner.readFloatFix(10) * M_PI / 180);
        _scanner.skipLine();
        constraints->add(constr.release());
        break;
    }
    case -14: // angles defined by 2 planes and range
    {
        std::unique_ptr<Molecule3dConstraints::AngleByPlanes> constr = std::make_unique<Molecule3dConstraints::AngleByPlanes>();
        _scanner.skip(6);
        constr->plane1_id = _scanner.readIntFix(3) - 1;
        constr->plane2_id = _scanner.readIntFix(3) - 1;
        constr->bottom = (float)(_scanner.readFloatFix(10) * M_PI / 180);
        constr->top = (float)(_scanner.readFloatFix(10) * M_PI / 180);
        _scanner.skipLine();

        constraints->add(constr.release());
        break;
    }
    case -15: // dihedral angle defined by 4 points
    {
        std::unique_ptr<Molecule3dConstraints::AngleDihedral> constr = std::make_unique<Molecule3dConstraints::AngleDihedral>();
        _scanner.skip(6);
        constr->point1_id = _scanner.readIntFix(3) - 1;
        constr->point2_id = _scanner.readIntFix(3) - 1;
        constr->point3_id = _scanner.readIntFix(3) - 1;
        constr->point4_id = _scanner.readIntFix(3) - 1;
        constr->bottom = (float)(_scanner.readFloatFix(10) * M_PI / 180);
        constr->top = (float)(_scanner.readFloatFix(10) * M_PI / 180);
        _scanner.skipLine();
        constraints->add(constr.release());
        break;
    }
    case -16: // exclusion sphere defines by points and distance
    {
        std::unique_ptr<Molecule3dConstraints::ExclusionSphere> constr = std::make_unique<Molecule3dConstraints::ExclusionSphere>();

        int allowed_atoms_amount;
        Array<int> allowed_atoms;
        _scanner.skip(6);
        constr->center_id = _scanner.readIntFix(3) - 1;
        constr->allow_unconnected = (_scanner.readIntFix(3) != 0);
        allowed_atoms_amount = _scanner.readIntFix(3);
        constr->radius = (float)(_scanner.readFloatFix(10));

        if (allowed_atoms_amount > 0)
        {
            _scanner.skipLine();
            _scanner.skip(6);

            while (allowed_atoms_amount-- > 0)
                constr->allowed_atoms.push(_scanner.readIntFix(3) - 1);
        }

        _scanner.skipLine();
        constraints->add(constr.release());
        break;
    }
    case -17: // fixed atoms
    {
        _scanner.skip(6);
        int amount = _scanner.readIntFix(3);
        _scanner.skipLine();
        _scanner.skip(6);

        while (amount-- > 0)
            _qmol->fixed_atoms.push(_scanner.readIntFix(3) - 1);

        _scanner.skipLine();
        break;
    }
    default:
        throw Error("unknown 3D feature in createFromMolfile: %d", feature_id);
    }
}