summaryrefslogtreecommitdiff
path: root/cad/plugins/CoNTub/src/AtomList.cpp
blob: ed7ee110234fdc634839622e8d2a07624f32aa51 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
// Copyright 2006-2007 Nanorex, Inc.  See LICENSE file for details. 
/* $Id$ */

/*
 * This is a C++ version of Java's AtomList class.
 */

#include <iostream>
#include <assert.h>
#include "AtomList.h"

AtomList::AtomList(void)
{
    _size = 0;
    capacity = 20;
    contents = new Atomo[capacity];
}

AtomList::AtomList(int n)
{
    _size = 0;
    if (n < 20)
	n = 20;
    capacity = n;
    contents = new Atomo[n];
}

AtomList::~AtomList(void)
{
    //delete[] contents;
}

Atomo * AtomList::get(int i)
{
    return &contents[i];
}

void AtomList::add(Atomo a)
{
    if (_size + 1 > capacity) {
	Atomo *newcontents;
	capacity *= 2;
	newcontents = new Atomo[capacity];
	for (int i = 0; i < _size; i++)
	    newcontents[i] = contents[i];
	// delete[] contents;
	contents = newcontents;
    }
    contents[_size++] = a;
}

int AtomList::size(void)
{
    return _size;
}

void AtomList::remove(int i)
{
    assert(i < _size);
    while (i + 1 < _size) {
	contents[i] = contents[i + 1];
	i++;
    }
    _size--;
}

void AtomList::set(int i, Atomo a)
{
    contents[i] = a;
}

int AtomList::contains(Atomo a)
{
    for (int i = 0; i < _size; i++) {
	assert(a.index != -1);
	assert(contents[i].index != -1);
	if (a.index == contents[i].index)
	    return 1;
    }
    return 0;
}

/*
 * There is a very effective optimization that can be used
 * for neighborhoods. I am not doing it here until I think
 * we need it, because it's a bit of work. As you add atoms
 * to the AtomList, you save a pointer to them in one of several
 * lists, pre-sorting atoms by coarse position. Doing so is
 * very quick. Then when you want the neighborhood around an
 * atom, you need only search the nearby buckets.
 */

#define GAP  (1.5 * 1.42)

int closeEnough(Atomo *a1, Atomo *a2)
{
    double distx = a1->vert.x - a2->vert.x;
    if (distx < -GAP || distx > GAP)
	return 0;
    double disty = a1->vert.y - a2->vert.y;
    if (disty < -GAP || disty > GAP)
	return 0;
    double distz = a1->vert.z - a2->vert.z;
    if (distz < -GAP || distz > GAP)
	return 0;
    double distsq = distx * distx + disty * disty +
	distz * distz;
    return distsq < GAP * GAP;
}

AtomList AtomList::neighborhood(Atomo *a)
{
    AtomList al = AtomList();
    for (int i = 0; i < _size; i++) {
	Atomo *b = &contents[i];
	if (closeEnough(a, b))
	    al.add(*b);
    }
    return al;
}