differentialProperties.cpp 10.1 KB
Newer Older
1 2 3 4 5
#include "differentialProperties.h"

#include "mapHandler.h"

#include "Algo/Geometry/normal.h"
6
#include "Algo/Geometry/curvature.h"
7 8 9

bool DifferentialPropertiesPlugin::enable()
{
10 11
	m_computeNormalDialog = new ComputeNormalDialog(m_window);
	m_computeCurvatureDialog = new ComputeCurvatureDialog(m_window);
12

13 14
	m_computeNormalAction = new QAction("Compute Normal", this);
	m_computeCurvatureAction = new QAction("Compute Curvature", this);
Pierre Kraemer's avatar
Pierre Kraemer committed
15

16 17
	addMenuAction("Surface;Differential Properties;Compute Normal", m_computeNormalAction);
	addMenuAction("Surface;Differential Properties;Compute Curvature", m_computeCurvatureAction);
Pierre Kraemer's avatar
Pierre Kraemer committed
18

19 20
	connect(m_computeNormalAction, SIGNAL(triggered()), this, SLOT(openComputeNormalDialog()));
	connect(m_computeCurvatureAction, SIGNAL(triggered()), this, SLOT(openComputeCurvatureDialog()));
21

22 23
	connect(m_computeNormalDialog, SIGNAL(accepted()), this, SLOT(computeNormalFromDialog()));
	connect(m_computeNormalDialog->button_apply, SIGNAL(clicked()), this, SLOT(computeNormalFromDialog()));
24

25 26
	connect(m_computeCurvatureDialog, SIGNAL(accepted()), this, SLOT(computeCurvatureFromDialog()));
	connect(m_computeCurvatureDialog->button_apply, SIGNAL(clicked()), this, SLOT(computeCurvatureFromDialog()));
27

28 29 30
	connect(m_window, SIGNAL(mapAdded(MapHandlerGen*)), this, SLOT(mapAdded(MapHandlerGen*)));
	connect(m_window, SIGNAL(mapRemoved(MapHandlerGen*)), this, SLOT(mapRemoved(MapHandlerGen*)));

31 32 33
	return true;
}

34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51
void DifferentialPropertiesPlugin::mapAdded(MapHandlerGen *map)
{
	connect(map, SIGNAL(attributeModified(unsigned int, QString)), this, SLOT(attributeModified(unsigned int, QString)));
}

void DifferentialPropertiesPlugin::mapRemoved(MapHandlerGen *map)
{
	disconnect(map, SIGNAL(attributeModified(unsigned int, QString)), this, SLOT(attributeModified(unsigned int, QString)));
}

void DifferentialPropertiesPlugin::attributeModified(unsigned int orbit, QString nameAttr)
{
	if(orbit == VERTEX)
	{
		MapHandlerGen* map = static_cast<MapHandlerGen*>(QObject::sender());
		if(computeNormalLastParameters.contains(map->getName()))
		{
			ComputeNormalParameters& params = computeNormalLastParameters[map->getName()];
Pierre Kraemer's avatar
Pierre Kraemer committed
52 53 54 55 56 57 58 59 60 61 62 63 64
			if(params.autoUpdate && params.positionName == nameAttr)
				computeNormal(map->getName(), params.positionName, params.normalName, true);
		}
		if(computeCurvatureLastParameters.contains(map->getName()))
		{
			ComputeCurvatureParameters& params = computeCurvatureLastParameters[map->getName()];
			if(params.autoUpdate && (params.positionName == nameAttr || params.normalName == nameAttr))
				computeCurvature(
					map->getName(),
					params.positionName, params.normalName,
					params.KmaxName, params.kmaxName, params.KminName, params.kminName, params.KnormalName,
					true
				);
65 66 67 68
		}
	}
}

69
void DifferentialPropertiesPlugin::openComputeNormalDialog()
70 71 72 73
{
	m_computeNormalDialog->show();
}

74
void DifferentialPropertiesPlugin::openComputeCurvatureDialog()
75
{
76
	m_computeCurvatureDialog->show();
77 78
}

79
void DifferentialPropertiesPlugin::computeNormalFromDialog()
80
{
81
	QList<QListWidgetItem*> currentItems = m_computeNormalDialog->mapList->selectedItems();
82 83
	if(!currentItems.empty())
	{
84
		const QString& mapName = currentItems[0]->text();
Pierre Kraemer's avatar
Pierre Kraemer committed
85

86
		QString positionName = m_computeNormalDialog->combo_positionAttribute->currentText();
87

88
		QString normalName;
89
		if(m_computeNormalDialog->normalAttributeName->text().isEmpty())
90
			normalName = m_computeNormalDialog->combo_normalAttribute->currentText();
91
		else
92
			normalName = m_computeNormalDialog->normalAttributeName->text();
93

94 95
		bool autoUpdate = (currentItems[0]->checkState() == Qt::Checked);

96
		computeNormal(mapName, positionName, normalName, autoUpdate);
97 98 99
	}
}

100
void DifferentialPropertiesPlugin::computeCurvatureFromDialog()
101 102 103 104
{
	QList<QListWidgetItem*> currentItems = m_computeCurvatureDialog->mapList->selectedItems();
	if(!currentItems.empty())
	{
105
		const QString& mapName = currentItems[0]->text();
106

107 108
		QString positionName = m_computeCurvatureDialog->combo_positionAttribute->currentText();
		QString normalName = m_computeCurvatureDialog->combo_normalAttribute->currentText();
109

110
		QString KmaxName;
111
		if(m_computeCurvatureDialog->KmaxAttributeName->text().isEmpty())
112
			KmaxName = m_computeCurvatureDialog->combo_KmaxAttribute->currentText();
113
		else
114
			KmaxName = m_computeCurvatureDialog->KmaxAttributeName->text();
115

116
		QString kmaxName;
117
		if(m_computeCurvatureDialog->kmaxAttributeName->text().isEmpty())
118
			kmaxName = m_computeCurvatureDialog->combo_kmaxAttribute->currentText();
119
		else
120
			kmaxName = m_computeCurvatureDialog->kmaxAttributeName->text();
121

122
		QString KminName;
123
		if(m_computeCurvatureDialog->KminAttributeName->text().isEmpty())
124
			KminName = m_computeCurvatureDialog->combo_KminAttribute->currentText();
125
		else
126
			KminName = m_computeCurvatureDialog->KminAttributeName->text();
127

128
		QString kminName;
129
		if(m_computeCurvatureDialog->kminAttributeName->text().isEmpty())
130
			kminName = m_computeCurvatureDialog->combo_kminAttribute->currentText();
131
		else
132
			kminName = m_computeCurvatureDialog->kminAttributeName->text();
133

134
		QString KnormalName;
135
		if(m_computeCurvatureDialog->KnormalAttributeName->text().isEmpty())
136
			KnormalName = m_computeCurvatureDialog->combo_KnormalAttribute->currentText();
137
		else
138
			KnormalName = m_computeCurvatureDialog->KnormalAttributeName->text();
139

140 141
		bool compute_kmean = (m_computeCurvatureDialog->check_computeKmean->checkState() == Qt::Checked);
		bool compute_kgaussian = (m_computeCurvatureDialog->check_computeKgaussian->checkState() == Qt::Checked);
142
		bool autoUpdate = (currentItems[0]->checkState() == Qt::Checked);
143

144
		computeCurvature(
145 146 147
			mapName,
			positionName, normalName,
			KmaxName, kmaxName, KminName, kminName, KnormalName,
148
			compute_kmean, compute_kgaussian,
149
			autoUpdate
150 151 152
		);
	}
}
153

154 155 156 157
void DifferentialPropertiesPlugin::computeNormal(
	const QString& mapName,
	const QString& positionAttributeName,
	const QString& normalAttributeName,
158
	bool autoUpdate)
159 160 161 162
{
	MapHandler<PFP2>* mh = static_cast<MapHandler<PFP2>*>(m_window->getMap(mapName));
	if(mh == NULL)
		return;
Pierre Kraemer's avatar
Pierre Kraemer committed
163

164 165 166 167 168 169 170 171 172 173 174
	VertexAttribute<PFP2::VEC3> position = mh->getAttribute<PFP2::VEC3, VERTEX>(positionAttributeName);
	if(!position.isValid())
		return;

	VertexAttribute<PFP2::VEC3> normal = mh->getAttribute<PFP2::VEC3, VERTEX>(normalAttributeName);
	if(!normal.isValid())
		normal = mh->addAttribute<PFP2::VEC3, VERTEX>(normalAttributeName);

	PFP2::MAP* map = mh->getMap();
	Algo::Surface::Geometry::computeNormalVertices<PFP2>(*map, position, normal);

175
	computeNormalLastParameters[mapName] =
176
		ComputeNormalParameters(positionAttributeName, normalAttributeName, autoUpdate);
177

178
	mh->createVBO(normal);
179

180
	mh->notifyAttributeModification(normal);
181 182 183 184 185 186 187 188 189 190 191
}

void DifferentialPropertiesPlugin::computeCurvature(
	const QString& mapName,
	const QString& positionAttributeName,
	const QString& normalAttributeName,
	const QString& KmaxAttributeName,
	const QString& kmaxAttributeName,
	const QString& KminAttributeName,
	const QString& kminAttributeName,
	const QString& KnormalAttributeName,
192 193
	bool compute_kmean,
	bool compute_kgaussian,
194
	bool autoUpdate)
195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233
{
	MapHandler<PFP2>* mh = static_cast<MapHandler<PFP2>*>(m_window->getMap(mapName));
	if(mh == NULL)
		return;

	VertexAttribute<PFP2::VEC3> position = mh->getAttribute<PFP2::VEC3, VERTEX>(positionAttributeName);
	if(!position.isValid())
		return;

	VertexAttribute<PFP2::VEC3> normal = mh->getAttribute<PFP2::VEC3, VERTEX>(normalAttributeName);
	if(!normal.isValid())
		return;

	VertexAttribute<PFP2::VEC3> Kmax = mh->getAttribute<PFP2::VEC3, VERTEX>(KmaxAttributeName);
	if(!Kmax.isValid())
		Kmax = mh->addAttribute<PFP2::VEC3, VERTEX>(KmaxAttributeName);

	VertexAttribute<PFP2::REAL> kmax = mh->getAttribute<PFP2::REAL, VERTEX>(kmaxAttributeName);
	if(!kmax.isValid())
		kmax = mh->addAttribute<PFP2::REAL, VERTEX>(kmaxAttributeName);

	VertexAttribute<PFP2::VEC3> Kmin = mh->getAttribute<PFP2::VEC3, VERTEX>(KminAttributeName);
	if(!Kmin.isValid())
		Kmin = mh->addAttribute<PFP2::VEC3, VERTEX>(KminAttributeName);

	VertexAttribute<PFP2::REAL> kmin = mh->getAttribute<PFP2::REAL, VERTEX>(kminAttributeName);
	if(!kmin.isValid())
		kmin = mh->addAttribute<PFP2::REAL, VERTEX>(kminAttributeName);

	VertexAttribute<PFP2::VEC3> Knormal = mh->getAttribute<PFP2::VEC3, VERTEX>(KnormalAttributeName);
	if(!Knormal.isValid())
		Knormal = mh->addAttribute<PFP2::VEC3, VERTEX>(KnormalAttributeName);

	EdgeAttribute<PFP2::REAL> edgeAngle = mh->getAttribute<PFP2::REAL, EDGE>("edgeAngle");
	if(!edgeAngle.isValid())
		edgeAngle = mh->addAttribute<PFP2::REAL, EDGE>("edgeAngle");

	PFP2::MAP* map = mh->getMap();
	Algo::Surface::Geometry::computeAnglesBetweenNormalsOnEdges<PFP2>(*map, position, edgeAngle);
234
	Algo::Surface::Geometry::computeCurvatureVertices_NormalCycles_Projected<PFP2>(*map, 0.01f * mh->getBBdiagSize(), position, normal, edgeAngle, kmax, kmin, Kmax, Kmin, Knormal);
235

236 237 238 239
	computeCurvatureLastParameters[mapName] =
		ComputeCurvatureParameters(
			positionAttributeName, normalAttributeName,
			KmaxAttributeName, kmaxAttributeName, KminAttributeName, kminAttributeName, KnormalAttributeName,
240
			compute_kmean, compute_kgaussian, autoUpdate);
241 242 243 244 245 246 247 248 249 250 251 252

	mh->createVBO(Kmax);
	mh->createVBO(kmax);
	mh->createVBO(Kmin);
	mh->createVBO(kmin);
	mh->createVBO(Knormal);

	mh->notifyAttributeModification(Kmax);
	mh->notifyAttributeModification(kmax);
	mh->notifyAttributeModification(Kmin);
	mh->notifyAttributeModification(kmin);
	mh->notifyAttributeModification(Knormal);
253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278

	if(compute_kmean)
	{
		VertexAttribute<PFP2::REAL> kmean = mh->getAttribute<PFP2::REAL, VERTEX>("kmean");
		if(!kmean.isValid())
			kmean = mh->addAttribute<PFP2::REAL, VERTEX>("kmean");

		for(unsigned int i = kmin.begin(); i != kmin.end(); kmin.next(i))
			kmean[i] = (kmin[i] + kmax[i]) / 2.0;

		mh->createVBO(kmean);
		mh->notifyAttributeModification(kmean);
	}

	if(compute_kgaussian)
	{
		VertexAttribute<PFP2::REAL> kgaussian = mh->getAttribute<PFP2::REAL, VERTEX>("kgaussian");
		if(!kgaussian.isValid())
			kgaussian = mh->addAttribute<PFP2::REAL, VERTEX>("kgaussian");

		for(unsigned int i = kmin.begin(); i != kmin.end(); kmin.next(i))
			kgaussian[i] = kmin[i] * kmax[i];

		mh->createVBO(kgaussian);
		mh->notifyAttributeModification(kgaussian);
	}
279 280
}

281 282 283 284 285
#ifndef DEBUG
Q_EXPORT_PLUGIN2(DifferentialPropertiesPlugin, DifferentialPropertiesPlugin)
#else
Q_EXPORT_PLUGIN2(DifferentialPropertiesPluginD, DifferentialPropertiesPlugin)
#endif