<commit_before>/*
Copyright (C) 2007 <SWGEmu>
This File is part of Core3.
This program is free software; you can redistribute
it and/or modify it under the terms of the GNU Lesser
General Public License as published by the Free Software
Foundation; either version 2 of the License,
or (at your option) any later version.

This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
See the GNU Lesser General Public License for
more details.

You should have received a copy of the GNU Lesser General
Public License along with this program; if not, write to
the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA

Linking Engine3 statically or dynamically with other modules
is making a combined work based on Engine3.
Thus, the terms and conditions of the GNU Lesser General Public License
cover the whole combination.

In addition, as a special exception, the copyright holders of Engine3
give you permission to combine Engine3 program with free software
programs or libraries that are released under the GNU LGPL and with
code included in the standard release of Core3 under the GNU LGPL
license (or modified versions of such code, with unchanged license).
You may copy and distribute such a system following the terms of the
GNU LGPL for Engine3 and the licenses of the other code concerned,
provided that you include the source code of that other code when
and as the GNU LGPL requires distribution of source code.

Note that people who make modified versions of Engine3 are not obligated
to grant this special exception for their modified versions;
it is their choice whether to do so. The GNU Lesser General Public License
gives permission to release a modified version without this exception;
this exception also makes it possible to release a modified version
which carries forward this exception.

 */

#include "LairObserver.h"
#include "server/zone/objects/scene/ObserverEventType.h"
#include "server/zone/objects/creature/NonPlayerCreatureObject.h"
#include "server/zone/packets/object/PlayClientEffectObjectMessage.h"
#include "server/zone/packets/scene/PlayClientEffectLocMessage.h"
#include "server/zone/managers/player/PlayerManager.h"
#include "server/zone/objects/tangible/weapon/WeaponObject.h"
#include "server/zone/objects/tangible/threat/ThreatMap.h"
#include "server/zone/Zone.h"
#include "HealLairObserverEvent.h"
#include "server/zone/managers/creature/CreatureManager.h"
#include "server/zone/managers/templates/TemplateManager.h"
#include "LairAggroTask.h"

int LairObserverImplementation::notifyObserverEvent(unsigned int eventType, Observable* observable, ManagedObject* arg1, int64 arg2) {
	switch (eventType) {
	case ObserverEventType::OBJECTDESTRUCTION:
		notifyDestruction(cast<TangibleObject*>(observable), cast<TangibleObject*>(arg1), (int)arg2);
		return 1;
		break;
	case ObserverEventType::DAMAGERECEIVED:

		int livingCreatureCount = getLivingCreatureCount();

		// if there are living creatures, make them aggro
		if(livingCreatureCount > 0 ){
			Reference<LairAggroTask*> task = new LairAggroTask(cast<TangibleObject*>(observable), cast<TangibleObject*>(arg1), _this.get());
			task->execute();
		}

		// if new creatures have spawned or there are live creatures near the lair
		if( checkForNewSpawns(cast<TangibleObject*>(observable)) || livingCreatureCount > 0 )
			checkForHeal(cast<TangibleObject*>(observable), cast<TangibleObject*>(arg1));

		break;
	}

	return 0;
}

void LairObserverImplementation::notifyDestruction(TangibleObject* lair, TangibleObject* attacker, int condition) {
	ThreatMap* threatMap = lair->getThreatMap();

	ThreatMap copyThreatMap(*threatMap);
	threatMap->removeObservers();
	threatMap->removeAll(); // we can clear the original one

	if (lair->getZone() == NULL) {
		spawnedCreatures.removeAll();
		return;
	}

	PlayClientEffectObjectMessage* explode = new PlayClientEffectObjectMessage(lair, "clienteffect/lair_damage_heavy.cef", "");
	lair->broadcastMessage(explode, false);

	PlayClientEffectLoc* explodeLoc = new PlayClientEffectLoc("clienteffect/lair_damage_heavy.cef", lair->getZone()->getZoneName(), lair->getPositionX(), lair->getPositionZ(), lair->getPositionY());
	lair->broadcastMessage(explodeLoc, false);

	lair->destroyObjectFromWorld(true);

	for (int i = 0; i < spawnedCreatures.size(); ++i) {
		CreatureObject* obj = spawnedCreatures.get(i);

		if (obj->isAiAgent())
			(cast<AiAgent*>(obj))->setDespawnOnNoPlayerInRange(true);
	}

	spawnedCreatures.removeAll();

	PlayerManager* playerManager = lair->getZoneServer()->getPlayerManager();
	playerManager->disseminateExperience(lair, &copyThreatMap);
}

void LairObserverImplementation::doAggro(TangibleObject* lair, TangibleObject* attacker){

	for (int i = 0; i < spawnedCreatures.size() ; ++i) {
			CreatureObject* creo = spawnedCreatures.get(i);

			if (creo->isDead() || creo->getZone() == NULL)
				continue;

			if (creo->isAiAgent() && (System::random(1) == 1) && attacker != NULL) {
				// TODO: only set defender if needed
				AiAgent* ai = cast<AiAgent*>( creo);
				Locker clocker(creo, lair);
				creo->setDefender(attacker);

			}
	}

}

void LairObserverImplementation::checkForHeal(TangibleObject* lair, TangibleObject* attacker, bool forceNewUpdate) {
	if (lair->isDestroyed() || getLairType() == LairTemplate::NPC)
		return;

	if (!(getLivingCreatureCount() > 0 && lair->getConditionDamage() > 0))
		return;

	if (healLairEvent == NULL) {
		healLairEvent = new HealLairObserverEvent(lair, attacker, _this.get());
		healLairEvent->schedule(1000);
	} else if (!healLairEvent->isScheduled()) {
		healLairEvent->schedule(1000);
	} else if (attacker != NULL)
		healLairEvent->setAttacker(attacker);
}

void LairObserverImplementation::healLair(TangibleObject* lair, TangibleObject* attacker){
	Locker locker(lair);

	if (lair->getZone() == NULL)
		return;

	int damageToHeal = 0;

	for (int i = 0; i < spawnedCreatures.size() ; ++i) {
		CreatureObject* creo = spawnedCreatures.get(i);

		if (creo->isDead() || creo->getZone() == NULL)
			continue;

		//  TODO: Range check
		damageToHeal += 100;

	}

	if (damageToHeal == 0)
		return;

	if (lair->getZone() == NULL)
		return;

	lair->healDamage(lair, 0, damageToHeal, true);

	PlayClientEffectObjectMessage* heal =
			new PlayClientEffectObjectMessage(lair, "clienteffect/healing_healdamage.cef", "");
	lair->broadcastMessage(heal, false);

	PlayClientEffectLoc* healLoc = new PlayClientEffectLoc("clienteffect/healing_healdamage.cef",
			lair->getZone()->getZoneName(), lair->getPositionX(),
			lair->getPositionZ(), lair->getPositionY());
	lair->broadcastMessage(healLoc, false);
}

bool LairObserverImplementation::checkForNewSpawns(TangibleObject* lair, bool forceSpawn) {
	if (lair->getZone() == NULL)
		return false;

	if (spawnedCreatures.size() >= lairTemplate->getSpawnLimit())
		return false;

	if (forceSpawn) {
		spawnNumber++;
	} else if (lairTemplate->getLairType() == LairTemplate::NPC) {
		return false;
	} else {
		int conditionDamage = lair->getConditionDamage();
		int maxCondition = lair->getMaxCondition();

		switch (spawnNumber) {
		case 0:
			spawnNumber++;
			break;
		case 1:
			if (conditionDamage > (maxCondition / 4)) {
				spawnNumber++;
			} else {
				return false;
			}
			break;
		case 2:
			if (conditionDamage > (maxCondition / 2)) {
				spawnNumber++;
			} else {
				return false;
			}
			break;
		case 3:
			return false;
			break;
		}
	}
	//SortedVector<uint32>* objectsToSpawn = getObjectsToSpawn();

	VectorMap<String, int>* objectsToSpawn = lairTemplate->getMobiles();
	int amountToSpawn = 0;

	if (lairTemplate->getLairType() == LairTemplate::CREATURE) {
		amountToSpawn = System::random(3) + ((lairTemplate->getSpawnLimit() / 3) - 2);
	} else {
		amountToSpawn = System::random(lairTemplate->getSpawnLimit() / 2) + (lairTemplate->getSpawnLimit() / 2);
	}

	if (amountToSpawn < 1)
		amountToSpawn = 1;

	for(int i = 0; i < amountToSpawn; ++i) {

		if (spawnedCreatures.size() >= lairTemplate->getSpawnLimit())
			return true;

		String templateToSpawn = objectsToSpawn->elementAt((int)System::random(objectsToSpawn->size() - 1)).getKey();

		CreatureManager* creatureManager = lair->getZone()->getCreatureManager();

		float x = lair->getPositionX() + (20.0f - System::random(400) / 10.0f);
		float y = lair->getPositionY() + (20.0f - System::random(400) / 10.0f);
		float z = lair->getZone()->getHeight(x, y);

		int levelDiff = objectsToSpawn->get(templateToSpawn);

		ManagedReference<CreatureObject*> creature = creatureManager->spawnCreatureWithLevel(templateToSpawn.hashCode(), difficulty + levelDiff, x, z, y);

		if (creature == NULL)
			return true;

		if (!creature->isAiAgent()) {
			error("spawned non player creature with template " + templateToSpawn);
		} else {
			AiAgent* npc = cast<AiAgent*>( creature.get());

			//Locker clocker(npc, lair);

			npc->setDespawnOnNoPlayerInRange(false);
			npc->setHomeLocation(x, z, y);
			npc->setRespawnTimer(0);

			spawnedCreatures.add(creature);
		}
	}

	return amountToSpawn > 0;
}

<commit_msg>[Changed] The amount that creatures heal their lair for to be based on the level of the lair instead of a static amount<commit_after>/*
Copyright (C) 2007 <SWGEmu>
This File is part of Core3.
This program is free software; you can redistribute
it and/or modify it under the terms of the GNU Lesser
General Public License as published by the Free Software
Foundation; either version 2 of the License,
or (at your option) any later version.

This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
See the GNU Lesser General Public License for
more details.

You should have received a copy of the GNU Lesser General
Public License along with this program; if not, write to
the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA

Linking Engine3 statically or dynamically with other modules
is making a combined work based on Engine3.
Thus, the terms and conditions of the GNU Lesser General Public License
cover the whole combination.

In addition, as a special exception, the copyright holders of Engine3
give you permission to combine Engine3 program with free software
programs or libraries that are released under the GNU LGPL and with
code included in the standard release of Core3 under the GNU LGPL
license (or modified versions of such code, with unchanged license).
You may copy and distribute such a system following the terms of the
GNU LGPL for Engine3 and the licenses of the other code concerned,
provided that you include the source code of that other code when
and as the GNU LGPL requires distribution of source code.

Note that people who make modified versions of Engine3 are not obligated
to grant this special exception for their modified versions;
it is their choice whether to do so. The GNU Lesser General Public License
gives permission to release a modified version without this exception;
this exception also makes it possible to release a modified version
which carries forward this exception.

 */

#include "LairObserver.h"
#include "server/zone/objects/scene/ObserverEventType.h"
#include "server/zone/objects/creature/NonPlayerCreatureObject.h"
#include "server/zone/packets/object/PlayClientEffectObjectMessage.h"
#include "server/zone/packets/scene/PlayClientEffectLocMessage.h"
#include "server/zone/managers/player/PlayerManager.h"
#include "server/zone/objects/tangible/weapon/WeaponObject.h"
#include "server/zone/objects/tangible/threat/ThreatMap.h"
#include "server/zone/Zone.h"
#include "HealLairObserverEvent.h"
#include "server/zone/managers/creature/CreatureManager.h"
#include "server/zone/managers/templates/TemplateManager.h"
#include "LairAggroTask.h"

int LairObserverImplementation::notifyObserverEvent(unsigned int eventType, Observable* observable, ManagedObject* arg1, int64 arg2) {
	switch (eventType) {
	case ObserverEventType::OBJECTDESTRUCTION:
		notifyDestruction(cast<TangibleObject*>(observable), cast<TangibleObject*>(arg1), (int)arg2);
		return 1;
		break;
	case ObserverEventType::DAMAGERECEIVED:

		int livingCreatureCount = getLivingCreatureCount();

		// if there are living creatures, make them aggro
		if(livingCreatureCount > 0 ){
			Reference<LairAggroTask*> task = new LairAggroTask(cast<TangibleObject*>(observable), cast<TangibleObject*>(arg1), _this.get());
			task->execute();
		}

		// if new creatures have spawned or there are live creatures near the lair
		if( checkForNewSpawns(cast<TangibleObject*>(observable)) || livingCreatureCount > 0 )
			checkForHeal(cast<TangibleObject*>(observable), cast<TangibleObject*>(arg1));

		break;
	}

	return 0;
}

void LairObserverImplementation::notifyDestruction(TangibleObject* lair, TangibleObject* attacker, int condition) {
	ThreatMap* threatMap = lair->getThreatMap();

	ThreatMap copyThreatMap(*threatMap);
	threatMap->removeObservers();
	threatMap->removeAll(); // we can clear the original one

	if (lair->getZone() == NULL) {
		spawnedCreatures.removeAll();
		return;
	}

	PlayClientEffectObjectMessage* explode = new PlayClientEffectObjectMessage(lair, "clienteffect/lair_damage_heavy.cef", "");
	lair->broadcastMessage(explode, false);

	PlayClientEffectLoc* explodeLoc = new PlayClientEffectLoc("clienteffect/lair_damage_heavy.cef", lair->getZone()->getZoneName(), lair->getPositionX(), lair->getPositionZ(), lair->getPositionY());
	lair->broadcastMessage(explodeLoc, false);

	lair->destroyObjectFromWorld(true);

	for (int i = 0; i < spawnedCreatures.size(); ++i) {
		CreatureObject* obj = spawnedCreatures.get(i);

		if (obj->isAiAgent())
			(cast<AiAgent*>(obj))->setDespawnOnNoPlayerInRange(true);
	}

	spawnedCreatures.removeAll();

	PlayerManager* playerManager = lair->getZoneServer()->getPlayerManager();
	playerManager->disseminateExperience(lair, &copyThreatMap);
}

void LairObserverImplementation::doAggro(TangibleObject* lair, TangibleObject* attacker){

	for (int i = 0; i < spawnedCreatures.size() ; ++i) {
			CreatureObject* creo = spawnedCreatures.get(i);

			if (creo->isDead() || creo->getZone() == NULL)
				continue;

			if (creo->isAiAgent() && (System::random(1) == 1) && attacker != NULL) {
				// TODO: only set defender if needed
				AiAgent* ai = cast<AiAgent*>( creo);
				Locker clocker(creo, lair);
				creo->setDefender(attacker);

			}
	}

}

void LairObserverImplementation::checkForHeal(TangibleObject* lair, TangibleObject* attacker, bool forceNewUpdate) {
	if (lair->isDestroyed() || getLairType() == LairTemplate::NPC)
		return;

	if (!(getLivingCreatureCount() > 0 && lair->getConditionDamage() > 0))
		return;

	if (healLairEvent == NULL) {
		healLairEvent = new HealLairObserverEvent(lair, attacker, _this.get());
		healLairEvent->schedule(1000);
	} else if (!healLairEvent->isScheduled()) {
		healLairEvent->schedule(1000);
	} else if (attacker != NULL)
		healLairEvent->setAttacker(attacker);
}

void LairObserverImplementation::healLair(TangibleObject* lair, TangibleObject* attacker){
	Locker locker(lair);

	if (lair->getZone() == NULL)
		return;

	int damageToHeal = 0;
	int lairMaxCondition = lair->getMaxCondition();

	for (int i = 0; i < spawnedCreatures.size() ; ++i) {
		CreatureObject* creo = spawnedCreatures.get(i);

		if (creo->isDead() || creo->getZone() == NULL)
			continue;

		//  TODO: Range check
		damageToHeal += lairMaxCondition / 100;

	}

	if (damageToHeal == 0)
		return;

	if (lair->getZone() == NULL)
		return;

	lair->healDamage(lair, 0, damageToHeal, true);

	PlayClientEffectObjectMessage* heal =
			new PlayClientEffectObjectMessage(lair, "clienteffect/healing_healdamage.cef", "");
	lair->broadcastMessage(heal, false);

	PlayClientEffectLoc* healLoc = new PlayClientEffectLoc("clienteffect/healing_healdamage.cef",
			lair->getZone()->getZoneName(), lair->getPositionX(),
			lair->getPositionZ(), lair->getPositionY());
	lair->broadcastMessage(healLoc, false);
}

bool LairObserverImplementation::checkForNewSpawns(TangibleObject* lair, bool forceSpawn) {
	if (lair->getZone() == NULL)
		return false;

	if (spawnedCreatures.size() >= lairTemplate->getSpawnLimit())
		return false;

	if (forceSpawn) {
		spawnNumber++;
	} else if (lairTemplate->getLairType() == LairTemplate::NPC) {
		return false;
	} else {
		int conditionDamage = lair->getConditionDamage();
		int maxCondition = lair->getMaxCondition();

		switch (spawnNumber) {
		case 0:
			spawnNumber++;
			break;
		case 1:
			if (conditionDamage > (maxCondition / 4)) {
				spawnNumber++;
			} else {
				return false;
			}
			break;
		case 2:
			if (conditionDamage > (maxCondition / 2)) {
				spawnNumber++;
			} else {
				return false;
			}
			break;
		case 3:
			return false;
			break;
		}
	}
	//SortedVector<uint32>* objectsToSpawn = getObjectsToSpawn();

	VectorMap<String, int>* objectsToSpawn = lairTemplate->getMobiles();
	int amountToSpawn = 0;

	if (lairTemplate->getLairType() == LairTemplate::CREATURE) {
		amountToSpawn = System::random(3) + ((lairTemplate->getSpawnLimit() / 3) - 2);
	} else {
		amountToSpawn = System::random(lairTemplate->getSpawnLimit() / 2) + (lairTemplate->getSpawnLimit() / 2);
	}

	if (amountToSpawn < 1)
		amountToSpawn = 1;

	for(int i = 0; i < amountToSpawn; ++i) {

		if (spawnedCreatures.size() >= lairTemplate->getSpawnLimit())
			return true;

		String templateToSpawn = objectsToSpawn->elementAt((int)System::random(objectsToSpawn->size() - 1)).getKey();

		CreatureManager* creatureManager = lair->getZone()->getCreatureManager();

		float x = lair->getPositionX() + (20.0f - System::random(400) / 10.0f);
		float y = lair->getPositionY() + (20.0f - System::random(400) / 10.0f);
		float z = lair->getZone()->getHeight(x, y);

		int levelDiff = objectsToSpawn->get(templateToSpawn);

		ManagedReference<CreatureObject*> creature = creatureManager->spawnCreatureWithLevel(templateToSpawn.hashCode(), difficulty + levelDiff, x, z, y);

		if (creature == NULL)
			return true;

		if (!creature->isAiAgent()) {
			error("spawned non player creature with template " + templateToSpawn);
		} else {
			AiAgent* npc = cast<AiAgent*>( creature.get());

			//Locker clocker(npc, lair);

			npc->setDespawnOnNoPlayerInRange(false);
			npc->setHomeLocation(x, z, y);
			npc->setRespawnTimer(0);

			spawnedCreatures.add(creature);
		}
	}

	return amountToSpawn > 0;
}

<|endoftext|>


<commit_before>/*
 * VehicleObjectImplementation.cpp
 *
 *  Created on: 10/04/2010
 *      Author: victor
 */

#include "server/zone/objects/creature/VehicleObject.h"
#include "server/zone/packets/object/ObjectMenuResponse.h"
#include "server/zone/objects/creature/CreatureObject.h"
#include "server/zone/objects/player/PlayerObject.h"
#include "server/zone/objects/intangible/VehicleControlDevice.h"
#include "server/zone/objects/building/BuildingObject.h"
#include "server/zone/Zone.h"
#include "server/zone/objects/player/sui/listbox/SuiListBox.h"
#include "server/zone/managers/planet/PlanetManager.h"
#include "server/zone/managers/structure/StructureManager.h"
#include "server/zone/objects/area/ActiveArea.h"
#include "server/zone/objects/region/CityRegion.h"
#include "server/zone/objects/creature/sui/RepairVehicleSuiCallback.h"
#include "server/zone/objects/region/CityRegion.h"
#include "server/zone/templates/customization/AssetCustomizationManagerTemplate.h"

void VehicleObjectImplementation::fillObjectMenuResponse(ObjectMenuResponse* menuResponse, CreatureObject* player) {
	if (!player->getPlayerObject()->isPrivileged() && linkedCreature != player)
		return;

	menuResponse->addRadialMenuItem(205, 1, "@pet/pet_menu:menu_enter_exit");
	menuResponse->addRadialMenuItem(61, 3, "");

	if (player->getPlayerObject()->isPrivileged() || (checkInRangeGarage() && !isDestroyed()))
		menuResponse->addRadialMenuItem(62, 3, "@pet/pet_menu:menu_repair_vehicle"); //Repair Vehicle
}

void VehicleObjectImplementation::fillAttributeList(AttributeListMessage* msg, CreatureObject* object){

	ManagedReference<CreatureObject* > linkedCreature = this->linkedCreature.get();
	if( linkedCreature == NULL )
		return;

	msg->insertAttribute("@obj_attr_n:owner", linkedCreature->getFirstName());

}

void VehicleObjectImplementation::notifyInsertToZone(Zone* zone) {
	SceneObjectImplementation::notifyInsertToZone(zone);

	if( this->linkedCreature == NULL )
		return;

	ManagedReference<CreatureObject* > linkedCreature = this->linkedCreature.get();
	if( linkedCreature == NULL )
		return;

	// Decay customized paint (if any)
	if (paintCount > 0){

		// Paint starts to fade when there are 4 calls left
		if (paintCount <= 4){

			// Send player notification of decay
			if( paintCount == 1 ){
				linkedCreature->sendSystemMessage("@pet/pet_menu:customization_gone_veh"); // "Your vehicle's customization has completely faded away."
			}
			else{
				linkedCreature->sendSystemMessage("@pet/pet_menu:customization_fading_veh"); // "Your vehicle's customization is fading away."
			}

			// Fade color to white
			String appearanceFilename = getObjectTemplate()->getAppearanceFilename();
			VectorMap<String, Reference<CustomizationVariable*> > variables;
			AssetCustomizationManagerTemplate::instance()->getCustomizationVariables(appearanceFilename.hashCode(), variables, false);
			for(int i = 0; i< variables.size(); ++i){
				String varkey = variables.elementAt(i).getKey();
				if (varkey.contains("color")){
					setCustomizationVariable(varkey, paintCount-1, true); // Palette values 3,2,1,0 are grey->white
				}
			}
		}
		--paintCount;
	}

}

bool VehicleObjectImplementation::checkInRangeGarage() {
	ManagedReference<SceneObject*> garage = StructureManager::instance()->getInRangeParkingGarage(_this.get());

	if (garage == NULL)
		return false;

	return true;
}

int VehicleObjectImplementation::handleObjectMenuSelect(CreatureObject* player, byte selectedID) {
	if (selectedID == 61 && linkedCreature == player) {
		unlock();

		try {
			ManagedReference<ControlDevice* > strongRef = controlDevice.get();

			if (strongRef != NULL)
				strongRef->storeObject(player);
		} catch (Exception& e) {

		} catch (...) {
			wlock(player);

			throw;
		}

		wlock(player);
	} else if (selectedID == 62) {
		repairVehicle(player);
	}

	return 0;
}

void VehicleObjectImplementation::repairVehicle(CreatureObject* player) {
	if (!player->getPlayerObject()->isPrivileged()) {
		//Need to check if they are city banned.

		ManagedReference<ActiveArea*> activeArea = getActiveRegion();

		if (activeArea != NULL && activeArea->isRegion()) {
			Region* region = cast<Region*>( activeArea.get());

			ManagedReference<CityRegion*> gb = region->getCityRegion();

			if (gb == NULL)
				return;

			if (gb->isBanned(player->getObjectID()))  {
				player->sendSystemMessage("@city/city:garage_banned"); //You are city banned and cannot use this garage.
				return;
			}

		if (getConditionDamage() == 0) {
			player->sendSystemMessage("@pet/pet_menu:undamaged_vehicle"); //The targeted vehicle does not require any repairs at the moment.
			return;
		}

		if (isDestroyed()) {
			player->sendSystemMessage("@pet/pet_menu:cannot_repair_disabled"); //You may not repair a disabled vehicle.
			return;
		}

		if (!checkInRangeGarage()) {
			player->sendSystemMessage("@pet/pet_menu:repair_unrecognized_garages"); //Your vehicle does not recognize any local garages. Try again in a garage repair zone.
			return;
			}
		}
	}
	sendRepairConfirmTo(player);
}

void VehicleObjectImplementation::sendRepairConfirmTo(CreatureObject* player) {
	ManagedReference<SuiListBox*> listbox = new SuiListBox(player, SuiWindowType::GARAGE_REPAIR);
    listbox->setCallback(new RepairVehicleSuiCallback(server->getZoneServer()));
	listbox->setPromptTitle("@pet/pet_menu:confirm_repairs_t"); //Confirm Vehicle Repairs
	listbox->setPromptText("@pet/pet_menu:vehicle_repair_d"); //You have chosen to repair your vehicle. Please review the listed details and confirm your selection.
	listbox->setUsingObject(_this.get());
	listbox->setCancelButton(true, "@cancel");

	int repairCost = calculateRepairCost(player);
	int totalFunds = player->getBankCredits();
	int tax = 0;

	ManagedReference<CityRegion*> city = getCityRegion();
	if(city != NULL && city->getGarageTax() > 0){
		repairCost += repairCost * city->getGarageTax() / 100;
	}

	listbox->addMenuItem("@pet/pet_menu:vehicle_prompt " + getDisplayedName()); //Vehicle:
	listbox->addMenuItem("@pet/pet_menu:repair_cost_prompt " + String::valueOf(repairCost)); //Repair Cost:
	listbox->addMenuItem("@pet/pet_menu:total_funds_prompt " + String::valueOf(totalFunds)); //Total Funds Available:

	player->getPlayerObject()->addSuiBox(listbox);
	player->sendMessage(listbox->generateMessage());
}

int VehicleObjectImplementation::calculateRepairCost(CreatureObject* player) {
	if (player->getPlayerObject()->isPrivileged())
		return 0;

	return getConditionDamage() * 5;
}

int VehicleObjectImplementation::inflictDamage(TangibleObject* attacker, int damageType, float damage, bool destroy, bool notifyClient) {
	return TangibleObjectImplementation::inflictDamage(attacker, damageType, damage, destroy, notifyClient);
}

int VehicleObjectImplementation::inflictDamage(TangibleObject* attacker, int damageType, float damage, bool destroy, const String& xp, bool notifyClient) {
	return TangibleObjectImplementation::inflictDamage(attacker, damageType, damage, destroy, xp, notifyClient);
}

int VehicleObjectImplementation::healDamage(TangibleObject* healer, int damageType, int damage, bool notifyClient) {
	return TangibleObjectImplementation::healDamage(healer, damageType, damage, notifyClient);
}

int VehicleObjectImplementation::notifyObjectDestructionObservers(TangibleObject* attacker, int condition) {
	unlock();

	ManagedReference<CreatureObject* > linkedCreature = this->linkedCreature.get();

	if (linkedCreature != NULL) {
		linkedCreature->sendSystemMessage("@pet/pet_menu:veh_disabled");
		try {
			if (attacker != _this.get()) {
				Locker clocker(linkedCreature, attacker);

				linkedCreature->executeObjectControllerAction(String("dismount").hashCode());

			} else {
				Locker locker(linkedCreature);

				linkedCreature->executeObjectControllerAction(String("dismount").hashCode());
			}

		} catch (Exception& e) {
		}
	}

	if (attacker != _this.get())
		wlock(attacker);
	else
		wlock();

	return CreatureObjectImplementation::notifyObjectDestructionObservers(attacker, condition);
}

void VehicleObjectImplementation::sendMessage(BasePacket* msg) {
	ManagedReference<CreatureObject* > linkedCreature = this->linkedCreature.get();

	if (linkedCreature != NULL && linkedCreature->getParent().get() == _this.get())
		linkedCreature->sendMessage(msg);
	else
		delete msg;
}

<commit_msg>[Fixed] Vehicle repair prices 0002611<commit_after>/*
 * VehicleObjectImplementation.cpp
 *
 *  Created on: 10/04/2010
 *      Author: victor
 */

#include "server/zone/objects/creature/VehicleObject.h"
#include "server/zone/packets/object/ObjectMenuResponse.h"
#include "server/zone/objects/creature/CreatureObject.h"
#include "server/zone/objects/player/PlayerObject.h"
#include "server/zone/objects/intangible/VehicleControlDevice.h"
#include "server/zone/objects/building/BuildingObject.h"
#include "server/zone/Zone.h"
#include "server/zone/objects/player/sui/listbox/SuiListBox.h"
#include "server/zone/managers/planet/PlanetManager.h"
#include "server/zone/managers/structure/StructureManager.h"
#include "server/zone/objects/area/ActiveArea.h"
#include "server/zone/objects/region/CityRegion.h"
#include "server/zone/objects/creature/sui/RepairVehicleSuiCallback.h"
#include "server/zone/objects/region/CityRegion.h"
#include "server/zone/templates/customization/AssetCustomizationManagerTemplate.h"

void VehicleObjectImplementation::fillObjectMenuResponse(ObjectMenuResponse* menuResponse, CreatureObject* player) {
	if (!player->getPlayerObject()->isPrivileged() && linkedCreature != player)
		return;

	menuResponse->addRadialMenuItem(205, 1, "@pet/pet_menu:menu_enter_exit");
	menuResponse->addRadialMenuItem(61, 3, "");

	if (player->getPlayerObject()->isPrivileged() || (checkInRangeGarage() && !isDestroyed()))
		menuResponse->addRadialMenuItem(62, 3, "@pet/pet_menu:menu_repair_vehicle"); //Repair Vehicle
}

void VehicleObjectImplementation::fillAttributeList(AttributeListMessage* msg, CreatureObject* object){

	ManagedReference<CreatureObject* > linkedCreature = this->linkedCreature.get();
	if( linkedCreature == NULL )
		return;

	msg->insertAttribute("@obj_attr_n:owner", linkedCreature->getFirstName());

}

void VehicleObjectImplementation::notifyInsertToZone(Zone* zone) {
	SceneObjectImplementation::notifyInsertToZone(zone);

	if( this->linkedCreature == NULL )
		return;

	ManagedReference<CreatureObject* > linkedCreature = this->linkedCreature.get();
	if( linkedCreature == NULL )
		return;

	// Decay customized paint (if any)
	if (paintCount > 0){

		// Paint starts to fade when there are 4 calls left
		if (paintCount <= 4){

			// Send player notification of decay
			if( paintCount == 1 ){
				linkedCreature->sendSystemMessage("@pet/pet_menu:customization_gone_veh"); // "Your vehicle's customization has completely faded away."
			}
			else{
				linkedCreature->sendSystemMessage("@pet/pet_menu:customization_fading_veh"); // "Your vehicle's customization is fading away."
			}

			// Fade color to white
			String appearanceFilename = getObjectTemplate()->getAppearanceFilename();
			VectorMap<String, Reference<CustomizationVariable*> > variables;
			AssetCustomizationManagerTemplate::instance()->getCustomizationVariables(appearanceFilename.hashCode(), variables, false);
			for(int i = 0; i< variables.size(); ++i){
				String varkey = variables.elementAt(i).getKey();
				if (varkey.contains("color")){
					setCustomizationVariable(varkey, paintCount-1, true); // Palette values 3,2,1,0 are grey->white
				}
			}
		}
		--paintCount;
	}

}

bool VehicleObjectImplementation::checkInRangeGarage() {
	ManagedReference<SceneObject*> garage = StructureManager::instance()->getInRangeParkingGarage(_this.get());

	if (garage == NULL)
		return false;

	return true;
}

int VehicleObjectImplementation::handleObjectMenuSelect(CreatureObject* player, byte selectedID) {
	if (selectedID == 61 && linkedCreature == player) {
		unlock();

		try {
			ManagedReference<ControlDevice* > strongRef = controlDevice.get();

			if (strongRef != NULL)
				strongRef->storeObject(player);
		} catch (Exception& e) {

		} catch (...) {
			wlock(player);

			throw;
		}

		wlock(player);
	} else if (selectedID == 62) {
		repairVehicle(player);
	}

	return 0;
}

void VehicleObjectImplementation::repairVehicle(CreatureObject* player) {
	if (!player->getPlayerObject()->isPrivileged()) {
		//Need to check if they are city banned.

		ManagedReference<ActiveArea*> activeArea = getActiveRegion();

		if (activeArea != NULL && activeArea->isRegion()) {
			Region* region = cast<Region*>( activeArea.get());

			ManagedReference<CityRegion*> gb = region->getCityRegion();

			if (gb == NULL)
				return;

			if (gb->isBanned(player->getObjectID()))  {
				player->sendSystemMessage("@city/city:garage_banned"); //You are city banned and cannot use this garage.
				return;
			}

		if (getConditionDamage() == 0) {
			player->sendSystemMessage("@pet/pet_menu:undamaged_vehicle"); //The targeted vehicle does not require any repairs at the moment.
			return;
		}

		if (isDestroyed()) {
			player->sendSystemMessage("@pet/pet_menu:cannot_repair_disabled"); //You may not repair a disabled vehicle.
			return;
		}

		if (!checkInRangeGarage()) {
			player->sendSystemMessage("@pet/pet_menu:repair_unrecognized_garages"); //Your vehicle does not recognize any local garages. Try again in a garage repair zone.
			return;
			}
		}
	}
	sendRepairConfirmTo(player);
}

void VehicleObjectImplementation::sendRepairConfirmTo(CreatureObject* player) {
	ManagedReference<SuiListBox*> listbox = new SuiListBox(player, SuiWindowType::GARAGE_REPAIR);
    listbox->setCallback(new RepairVehicleSuiCallback(server->getZoneServer()));
	listbox->setPromptTitle("@pet/pet_menu:confirm_repairs_t"); //Confirm Vehicle Repairs
	listbox->setPromptText("@pet/pet_menu:vehicle_repair_d"); //You have chosen to repair your vehicle. Please review the listed details and confirm your selection.
	listbox->setUsingObject(_this.get());
	listbox->setCancelButton(true, "@cancel");

	int repairCost = calculateRepairCost(player);
	int totalFunds = player->getBankCredits();
	int tax = 0;

	ManagedReference<CityRegion*> city = getCityRegion();
	if(city != NULL && city->getGarageTax() > 0){
		repairCost += repairCost * city->getGarageTax() / 100;
	}

	listbox->addMenuItem("@pet/pet_menu:vehicle_prompt " + getDisplayedName()); //Vehicle:
	listbox->addMenuItem("@pet/pet_menu:repair_cost_prompt " + String::valueOf(repairCost)); //Repair Cost:
	listbox->addMenuItem("@pet/pet_menu:total_funds_prompt " + String::valueOf(totalFunds)); //Total Funds Available:

	player->getPlayerObject()->addSuiBox(listbox);
	player->sendMessage(listbox->generateMessage());
}

int VehicleObjectImplementation::calculateRepairCost(CreatureObject* player) {
	if (player->getPlayerObject()->isPrivileged())
		return 0;

	return getConditionDamage() * 4;
}

int VehicleObjectImplementation::inflictDamage(TangibleObject* attacker, int damageType, float damage, bool destroy, bool notifyClient) {
	return TangibleObjectImplementation::inflictDamage(attacker, damageType, damage, destroy, notifyClient);
}

int VehicleObjectImplementation::inflictDamage(TangibleObject* attacker, int damageType, float damage, bool destroy, const String& xp, bool notifyClient) {
	return TangibleObjectImplementation::inflictDamage(attacker, damageType, damage, destroy, xp, notifyClient);
}

int VehicleObjectImplementation::healDamage(TangibleObject* healer, int damageType, int damage, bool notifyClient) {
	return TangibleObjectImplementation::healDamage(healer, damageType, damage, notifyClient);
}

int VehicleObjectImplementation::notifyObjectDestructionObservers(TangibleObject* attacker, int condition) {
	unlock();

	ManagedReference<CreatureObject* > linkedCreature = this->linkedCreature.get();

	if (linkedCreature != NULL) {
		linkedCreature->sendSystemMessage("@pet/pet_menu:veh_disabled");
		try {
			if (attacker != _this.get()) {
				Locker clocker(linkedCreature, attacker);

				linkedCreature->executeObjectControllerAction(String("dismount").hashCode());

			} else {
				Locker locker(linkedCreature);

				linkedCreature->executeObjectControllerAction(String("dismount").hashCode());
			}

		} catch (Exception& e) {
		}
	}

	if (attacker != _this.get())
		wlock(attacker);
	else
		wlock();

	return CreatureObjectImplementation::notifyObjectDestructionObservers(attacker, condition);
}

void VehicleObjectImplementation::sendMessage(BasePacket* msg) {
	ManagedReference<CreatureObject* > linkedCreature = this->linkedCreature.get();

	if (linkedCreature != NULL && linkedCreature->getParent().get() == _this.get())
		linkedCreature->sendMessage(msg);
	else
		delete msg;
}

<|endoftext|>


<commit_before>/*===================================================================

The Medical Imaging Interaction Toolkit (MITK)

Copyright (c) German Cancer Research Center,
Division of Medical and Biological Informatics.
All rights reserved.

This software is distributed WITHOUT ANY WARRANTY; without
even the implied warranty of MERCHANTABILITY or FITNESS FOR
A PARTICULAR PURPOSE.

See LICENSE.txt or http://www.mitk.org for details.

===================================================================*/

#include "mitkPlanarFigureSegmentationController.h"

#include "mitkSurfaceToImageFilter.h"

#include <vtkPolyData.h>
#include <vtkPoints.h>
#include <vtkPolygon.h>
#include <vtkCellArray.h>

#include <vtkSmartPointer.h>
#include <vtkImageData.h>
#include "mitkImageWriter.h"
#include "mitkSurfaceVtkWriter.h"
#include "mitkImageToSurfaceFilter.h"

#include "mitkImageAccessByItk.h"

#include "mitkImageCast.h"

mitk::PlanarFigureSegmentationController::PlanarFigureSegmentationController()
: itk::Object()
, m_ReduceFilter( NULL )
, m_NormalsFilter( NULL )
, m_DistanceImageCreator( NULL )
, m_ReferenceImage( NULL )
, m_SegmentationAsImage( NULL )
{
  InitializeFilters();
}

mitk::PlanarFigureSegmentationController::~PlanarFigureSegmentationController()
{
}

void mitk::PlanarFigureSegmentationController::SetReferenceImage( mitk::Image::Pointer referenceImage )
{
  m_ReferenceImage = referenceImage;
}

void mitk::PlanarFigureSegmentationController::AddPlanarFigure( mitk::PlanarFigure::Pointer planarFigure )
{
  if ( planarFigure.IsNull() )
    return;

  bool newFigure = true;
  int indexOfFigure = -1;
  for( int i=0; i<m_PlanarFigureList.size(); i++ )
  {
    if( m_PlanarFigureList.at(i) == planarFigure )
    {
      indexOfFigure = i;
      newFigure = false;
      break;
    }
  }

  mitk::Surface::Pointer figureAsSurface = NULL;

  if ( newFigure )
  {
    m_PlanarFigureList.push_back( planarFigure );
    figureAsSurface = this->CreateSurfaceFromPlanarFigure( planarFigure );
    m_SurfaceList.push_back( figureAsSurface );
    indexOfFigure = m_PlanarFigureList.size() -1 ;
  }
  else
  {
    figureAsSurface = this->CreateSurfaceFromPlanarFigure( planarFigure );
    m_SurfaceList.at(indexOfFigure) = figureAsSurface;
  }

  m_ReduceFilter->SetInput( indexOfFigure, figureAsSurface );

  m_NormalsFilter->SetInput( indexOfFigure, m_ReduceFilter->GetOutput( indexOfFigure ) );
  m_DistanceImageCreator->SetInput( indexOfFigure, m_NormalsFilter->GetOutput( indexOfFigure ) );
}

void mitk::PlanarFigureSegmentationController::RemovePlanarFigure( mitk::PlanarFigure::Pointer planarFigure )
{
  if ( planarFigure.IsNull() )
    return;

  bool figureFound = false;
  int indexOfFigure = -1;
  for( int i=0; i<m_PlanarFigureList.size(); i++ )
  {
    if( m_PlanarFigureList.at(i) == planarFigure )
    {
      indexOfFigure = i;
      figureFound = true;
      break;
    }
  }

  if ( !figureFound )
    return;

  if ( indexOfFigure == m_PlanarFigureList.size()-1 )
  {
    // Ff the removed figure was the last one in the list, we can simply
    // remove the last input from each filter.
    m_DistanceImageCreator->RemoveInputs( m_NormalsFilter->GetOutput( indexOfFigure ) );
    m_NormalsFilter->RemoveInputs( m_ReduceFilter->GetOutput( indexOfFigure ) );
    m_ReduceFilter->RemoveInputs( const_cast<mitk::Surface*>(m_ReduceFilter->GetInput(indexOfFigure)) );
  }
  else
  {
    // this is not very nice! If the figure that has been removed is NOT the last
    // one in the list we have to create new filters and add all remaining
    // inputs again.
    //
    // Has to be done as the filters do not work when removing an input
    // other than the last one.

    // create new filters
    InitializeFilters();

    // and add all existing surfaces
    SurfaceListType::iterator surfaceIter = m_SurfaceList.begin();
    for ( surfaceIter = m_SurfaceList.begin(); surfaceIter!=m_SurfaceList.end(); surfaceIter++ )
    {
      m_ReduceFilter->SetInput( indexOfFigure, (*surfaceIter) );
      m_NormalsFilter->SetInput( indexOfFigure, m_ReduceFilter->GetOutput( indexOfFigure ) );
      m_DistanceImageCreator->SetInput( indexOfFigure, m_NormalsFilter->GetOutput( indexOfFigure ) );
    }
  }

  PlanarFigureListType::iterator whereIter = m_PlanarFigureList.begin();
  whereIter += indexOfFigure;
  m_PlanarFigureList.erase( whereIter );

  SurfaceListType::iterator surfaceIter = m_SurfaceList.begin();
  surfaceIter += indexOfFigure;
  m_SurfaceList.erase( surfaceIter );
}

template<typename TPixel, unsigned int VImageDimension>
void mitk::PlanarFigureSegmentationController::GetImageBase(itk::Image<TPixel, VImageDimension>* input, itk::ImageBase<3>::Pointer& result)
{
  result = input;
}

mitk::Image::Pointer mitk::PlanarFigureSegmentationController::GetInterpolationResult()
{
  m_SegmentationAsImage = NULL;

  if ( m_PlanarFigureList.size() == 0 )
  {
    m_SegmentationAsImage = mitk::Image::New();
    m_SegmentationAsImage->Initialize(mitk::MakeScalarPixelType<unsigned char>() , *m_ReferenceImage->GetTimeSlicedGeometry());

    return m_SegmentationAsImage;
  }

  itk::ImageBase<3>::Pointer itkImage;
  AccessFixedDimensionByItk_1( m_ReferenceImage.GetPointer(), GetImageBase, 3, itkImage );
  m_DistanceImageCreator->SetReferenceImage( itkImage.GetPointer() );

  m_ReduceFilter->Update();
  m_NormalsFilter->Update();
  m_DistanceImageCreator->Update();

  mitk::Image::Pointer distanceImage = m_DistanceImageCreator->GetOutput();

  // Cleanup the pipeline
  distanceImage->DisconnectPipeline();
  m_DistanceImageCreator = NULL;
  m_NormalsFilter = NULL;
  m_ReduceFilter = NULL;
  itkImage = NULL;

  // If this bool flag is true, the distanceImage will be written to the
  // filesystem as nrrd-image and as surface-representation.
  bool debugOutput(false);
  if ( debugOutput )
  {
    mitk::ImageWriter::Pointer imageWriter = mitk::ImageWriter::New();
    imageWriter->SetInput( distanceImage );
    imageWriter->SetExtension( ".nrrd" );
    imageWriter->SetFileName( "v:/DistanceImage" );
    imageWriter->Update();
  }

  mitk::ImageToSurfaceFilter::Pointer imageToSurfaceFilter = mitk::ImageToSurfaceFilter::New();
  imageToSurfaceFilter->SetInput( distanceImage );
  imageToSurfaceFilter->SetThreshold( 0 );
  imageToSurfaceFilter->Update();

  mitk::Surface::Pointer segmentationAsSurface = imageToSurfaceFilter->GetOutput();

  // Cleanup the pipeline
  segmentationAsSurface->DisconnectPipeline();
  imageToSurfaceFilter = NULL;

  if ( debugOutput )
  {
    mitk::SurfaceVtkWriter<vtkPolyDataWriter>::Pointer surfaceWriter = mitk::SurfaceVtkWriter<vtkPolyDataWriter>::New();
    surfaceWriter->SetInput( segmentationAsSurface );
    surfaceWriter->SetExtension( ".vtk" );
    surfaceWriter->SetFileName( "v:/DistanceImageAsSurface.vtk" );
    surfaceWriter->Update();
  }

  mitk::SurfaceToImageFilter::Pointer surfaceToImageFilter = mitk::SurfaceToImageFilter::New();
  surfaceToImageFilter->SetInput( segmentationAsSurface );
  surfaceToImageFilter->SetImage( m_ReferenceImage );
  surfaceToImageFilter->SetMakeOutputBinary(true);
  surfaceToImageFilter->Update();

  m_SegmentationAsImage = surfaceToImageFilter->GetOutput();

  // Cleanup the pipeline
  m_SegmentationAsImage->DisconnectPipeline();

  return m_SegmentationAsImage;
}

mitk::Surface::Pointer mitk::PlanarFigureSegmentationController::CreateSurfaceFromPlanarFigure( mitk::PlanarFigure::Pointer figure )
{
  if ( figure.IsNull() )
  {
    MITK_ERROR << "Given PlanarFigure is NULL. Please provide valid PlanarFigure.";
    return NULL;
  }

  mitk::Surface::Pointer newSurface = mitk::Surface::New();

  vtkSmartPointer<vtkPoints> points = vtkSmartPointer<vtkPoints>::New();
  vtkSmartPointer<vtkPolygon> polygon = vtkSmartPointer<vtkPolygon>::New();
  vtkSmartPointer<vtkCellArray> cells = vtkSmartPointer<vtkCellArray>::New();
  vtkSmartPointer<vtkPolyData> polyData = vtkSmartPointer<vtkPolyData>::New();

  const mitk::Geometry2D* figureGeometry = figure->GetGeometry2D();

  // Get the polyline
  mitk::PlanarFigure::PolyLineType planarPolyLine = figure->GetPolyLine(0);
  mitk::PlanarFigure::PolyLineType::iterator iter;

  // iterate over the polyline, ...
  int pointCounter = 0;
  for( iter = planarPolyLine.begin(); iter != planarPolyLine.end(); iter++ )
  {
    // ... determine the world-coordinates
    mitk::Point2D polyLinePoint = iter->Point;
    mitk::Point3D pointInWorldCoordiantes;
    figureGeometry->Map( polyLinePoint, pointInWorldCoordiantes );

    // and add them as new points to the vtkPoints
    points->InsertNextPoint( pointInWorldCoordiantes[0], pointInWorldCoordiantes[1], pointInWorldCoordiantes[2] );
    ++pointCounter;
  }

  // create a polygon with the points of the polyline
  polygon->GetPointIds()->SetNumberOfIds( pointCounter );
  for(unsigned int i = 0; i < pointCounter; i++)
  {
    polygon->GetPointIds()->SetId(i,i);
  }

  // initialize the vtkCellArray and vtkPolyData
  cells->InsertNextCell(polygon);
  polyData->SetPoints(points);
  polyData->SetPolys( cells );

  // set the polydata to the surface
  newSurface->SetVtkPolyData( polyData );

  return newSurface;
}

mitk::PlanarFigureSegmentationController::PlanarFigureListType mitk::PlanarFigureSegmentationController::GetAllPlanarFigures()
{
  return m_PlanarFigureList;
}

void mitk::PlanarFigureSegmentationController::InitializeFilters()
{
  m_ReduceFilter = mitk::ReduceContourSetFilter::New();
  m_ReduceFilter->SetReductionType(ReduceContourSetFilter::NTH_POINT);
  m_ReduceFilter->SetStepSize( 10 );
  m_NormalsFilter = mitk::ComputeContourSetNormalsFilter::New();
  m_DistanceImageCreator = mitk::CreateDistanceImageFromSurfaceFilter::New();
}

<commit_msg>commented code that uses deprecated ITK methods<commit_after>/*===================================================================

The Medical Imaging Interaction Toolkit (MITK)

Copyright (c) German Cancer Research Center,
Division of Medical and Biological Informatics.
All rights reserved.

This software is distributed WITHOUT ANY WARRANTY; without
even the implied warranty of MERCHANTABILITY or FITNESS FOR
A PARTICULAR PURPOSE.

See LICENSE.txt or http://www.mitk.org for details.

===================================================================*/

#include "mitkPlanarFigureSegmentationController.h"

#include "mitkSurfaceToImageFilter.h"

#include <vtkPolyData.h>
#include <vtkPoints.h>
#include <vtkPolygon.h>
#include <vtkCellArray.h>

#include <vtkSmartPointer.h>
#include <vtkImageData.h>
#include "mitkImageWriter.h"
#include "mitkSurfaceVtkWriter.h"
#include "mitkImageToSurfaceFilter.h"

#include "mitkImageAccessByItk.h"

#include "mitkImageCast.h"

mitk::PlanarFigureSegmentationController::PlanarFigureSegmentationController()
: itk::Object()
, m_ReduceFilter( NULL )
, m_NormalsFilter( NULL )
, m_DistanceImageCreator( NULL )
, m_ReferenceImage( NULL )
, m_SegmentationAsImage( NULL )
{
  InitializeFilters();
}

mitk::PlanarFigureSegmentationController::~PlanarFigureSegmentationController()
{
}

void mitk::PlanarFigureSegmentationController::SetReferenceImage( mitk::Image::Pointer referenceImage )
{
  m_ReferenceImage = referenceImage;
}

void mitk::PlanarFigureSegmentationController::AddPlanarFigure( mitk::PlanarFigure::Pointer planarFigure )
{
  if ( planarFigure.IsNull() )
    return;

  bool newFigure = true;
  int indexOfFigure = -1;
  for( int i=0; i<m_PlanarFigureList.size(); i++ )
  {
    if( m_PlanarFigureList.at(i) == planarFigure )
    {
      indexOfFigure = i;
      newFigure = false;
      break;
    }
  }

  mitk::Surface::Pointer figureAsSurface = NULL;

  if ( newFigure )
  {
    m_PlanarFigureList.push_back( planarFigure );
    figureAsSurface = this->CreateSurfaceFromPlanarFigure( planarFigure );
    m_SurfaceList.push_back( figureAsSurface );
    indexOfFigure = m_PlanarFigureList.size() -1 ;
  }
  else
  {
    figureAsSurface = this->CreateSurfaceFromPlanarFigure( planarFigure );
    m_SurfaceList.at(indexOfFigure) = figureAsSurface;
  }

  m_ReduceFilter->SetInput( indexOfFigure, figureAsSurface );

  m_NormalsFilter->SetInput( indexOfFigure, m_ReduceFilter->GetOutput( indexOfFigure ) );
  m_DistanceImageCreator->SetInput( indexOfFigure, m_NormalsFilter->GetOutput( indexOfFigure ) );
}

void mitk::PlanarFigureSegmentationController::RemovePlanarFigure( mitk::PlanarFigure::Pointer planarFigure )
{
  if ( planarFigure.IsNull() )
    return;

  bool figureFound = false;
  int indexOfFigure = -1;
  for( int i=0; i<m_PlanarFigureList.size(); i++ )
  {
    if( m_PlanarFigureList.at(i) == planarFigure )
    {
      indexOfFigure = i;
      figureFound = true;
      break;
    }
  }

  if ( !figureFound )
    return;

  // TODO: fix this! The following code had to be removed as the method
  // RemoveInputs() has been removed in ITK 4
  // The remaining code works correctly but is slower
  if ( false && indexOfFigure == m_PlanarFigureList.size()-1 )
  {
    // Ff the removed figure was the last one in the list, we can simply
    // remove the last input from each filter.
//     m_DistanceImageCreator->RemoveInputs( m_NormalsFilter->GetOutput( indexOfFigure ) );
//     m_NormalsFilter->RemoveInput( m_ReduceFilter->GetOutput( indexOfFigure ) );
//     m_ReduceFilter->RemoveInput( const_cast<mitk::Surface*>(m_ReduceFilter->GetInput(indexOfFigure)) );
  }
  else
  {
    // this is not very nice! If the figure that has been removed is NOT the last
    // one in the list we have to create new filters and add all remaining
    // inputs again.
    //
    // Has to be done as the filters do not work when removing an input
    // other than the last one.

    // create new filters
    InitializeFilters();

    // and add all existing surfaces
    SurfaceListType::iterator surfaceIter = m_SurfaceList.begin();
    for ( surfaceIter = m_SurfaceList.begin(); surfaceIter!=m_SurfaceList.end(); surfaceIter++ )
    {
      m_ReduceFilter->SetInput( indexOfFigure, (*surfaceIter) );
      m_NormalsFilter->SetInput( indexOfFigure, m_ReduceFilter->GetOutput( indexOfFigure ) );
      m_DistanceImageCreator->SetInput( indexOfFigure, m_NormalsFilter->GetOutput( indexOfFigure ) );
    }
  }

  PlanarFigureListType::iterator whereIter = m_PlanarFigureList.begin();
  whereIter += indexOfFigure;
  m_PlanarFigureList.erase( whereIter );

  SurfaceListType::iterator surfaceIter = m_SurfaceList.begin();
  surfaceIter += indexOfFigure;
  m_SurfaceList.erase( surfaceIter );
}

template<typename TPixel, unsigned int VImageDimension>
void mitk::PlanarFigureSegmentationController::GetImageBase(itk::Image<TPixel, VImageDimension>* input, itk::ImageBase<3>::Pointer& result)
{
  result = input;
}

mitk::Image::Pointer mitk::PlanarFigureSegmentationController::GetInterpolationResult()
{
  m_SegmentationAsImage = NULL;

  if ( m_PlanarFigureList.size() == 0 )
  {
    m_SegmentationAsImage = mitk::Image::New();
    m_SegmentationAsImage->Initialize(mitk::MakeScalarPixelType<unsigned char>() , *m_ReferenceImage->GetTimeSlicedGeometry());

    return m_SegmentationAsImage;
  }

  itk::ImageBase<3>::Pointer itkImage;
  AccessFixedDimensionByItk_1( m_ReferenceImage.GetPointer(), GetImageBase, 3, itkImage );
  m_DistanceImageCreator->SetReferenceImage( itkImage.GetPointer() );

  m_ReduceFilter->Update();
  m_NormalsFilter->Update();
  m_DistanceImageCreator->Update();

  mitk::Image::Pointer distanceImage = m_DistanceImageCreator->GetOutput();

  // Cleanup the pipeline
  distanceImage->DisconnectPipeline();
  m_DistanceImageCreator = NULL;
  m_NormalsFilter = NULL;
  m_ReduceFilter = NULL;
  itkImage = NULL;

  // If this bool flag is true, the distanceImage will be written to the
  // filesystem as nrrd-image and as surface-representation.
  bool debugOutput(false);
  if ( debugOutput )
  {
    mitk::ImageWriter::Pointer imageWriter = mitk::ImageWriter::New();
    imageWriter->SetInput( distanceImage );
    imageWriter->SetExtension( ".nrrd" );
    imageWriter->SetFileName( "v:/DistanceImage" );
    imageWriter->Update();
  }

  mitk::ImageToSurfaceFilter::Pointer imageToSurfaceFilter = mitk::ImageToSurfaceFilter::New();
  imageToSurfaceFilter->SetInput( distanceImage );
  imageToSurfaceFilter->SetThreshold( 0 );
  imageToSurfaceFilter->Update();

  mitk::Surface::Pointer segmentationAsSurface = imageToSurfaceFilter->GetOutput();

  // Cleanup the pipeline
  segmentationAsSurface->DisconnectPipeline();
  imageToSurfaceFilter = NULL;

  if ( debugOutput )
  {
    mitk::SurfaceVtkWriter<vtkPolyDataWriter>::Pointer surfaceWriter = mitk::SurfaceVtkWriter<vtkPolyDataWriter>::New();
    surfaceWriter->SetInput( segmentationAsSurface );
    surfaceWriter->SetExtension( ".vtk" );
    surfaceWriter->SetFileName( "v:/DistanceImageAsSurface.vtk" );
    surfaceWriter->Update();
  }

  mitk::SurfaceToImageFilter::Pointer surfaceToImageFilter = mitk::SurfaceToImageFilter::New();
  surfaceToImageFilter->SetInput( segmentationAsSurface );
  surfaceToImageFilter->SetImage( m_ReferenceImage );
  surfaceToImageFilter->SetMakeOutputBinary(true);
  surfaceToImageFilter->Update();

  m_SegmentationAsImage = surfaceToImageFilter->GetOutput();

  // Cleanup the pipeline
  m_SegmentationAsImage->DisconnectPipeline();

  return m_SegmentationAsImage;
}

mitk::Surface::Pointer mitk::PlanarFigureSegmentationController::CreateSurfaceFromPlanarFigure( mitk::PlanarFigure::Pointer figure )
{
  if ( figure.IsNull() )
  {
    MITK_ERROR << "Given PlanarFigure is NULL. Please provide valid PlanarFigure.";
    return NULL;
  }

  mitk::Surface::Pointer newSurface = mitk::Surface::New();

  vtkSmartPointer<vtkPoints> points = vtkSmartPointer<vtkPoints>::New();
  vtkSmartPointer<vtkPolygon> polygon = vtkSmartPointer<vtkPolygon>::New();
  vtkSmartPointer<vtkCellArray> cells = vtkSmartPointer<vtkCellArray>::New();
  vtkSmartPointer<vtkPolyData> polyData = vtkSmartPointer<vtkPolyData>::New();

  const mitk::Geometry2D* figureGeometry = figure->GetGeometry2D();

  // Get the polyline
  mitk::PlanarFigure::PolyLineType planarPolyLine = figure->GetPolyLine(0);
  mitk::PlanarFigure::PolyLineType::iterator iter;

  // iterate over the polyline, ...
  int pointCounter = 0;
  for( iter = planarPolyLine.begin(); iter != planarPolyLine.end(); iter++ )
  {
    // ... determine the world-coordinates
    mitk::Point2D polyLinePoint = iter->Point;
    mitk::Point3D pointInWorldCoordiantes;
    figureGeometry->Map( polyLinePoint, pointInWorldCoordiantes );

    // and add them as new points to the vtkPoints
    points->InsertNextPoint( pointInWorldCoordiantes[0], pointInWorldCoordiantes[1], pointInWorldCoordiantes[2] );
    ++pointCounter;
  }

  // create a polygon with the points of the polyline
  polygon->GetPointIds()->SetNumberOfIds( pointCounter );
  for(unsigned int i = 0; i < pointCounter; i++)
  {
    polygon->GetPointIds()->SetId(i,i);
  }

  // initialize the vtkCellArray and vtkPolyData
  cells->InsertNextCell(polygon);
  polyData->SetPoints(points);
  polyData->SetPolys( cells );

  // set the polydata to the surface
  newSurface->SetVtkPolyData( polyData );

  return newSurface;
}

mitk::PlanarFigureSegmentationController::PlanarFigureListType mitk::PlanarFigureSegmentationController::GetAllPlanarFigures()
{
  return m_PlanarFigureList;
}

void mitk::PlanarFigureSegmentationController::InitializeFilters()
{
  m_ReduceFilter = mitk::ReduceContourSetFilter::New();
  m_ReduceFilter->SetReductionType(ReduceContourSetFilter::NTH_POINT);
  m_ReduceFilter->SetStepSize( 10 );
  m_NormalsFilter = mitk::ComputeContourSetNormalsFilter::New();
  m_DistanceImageCreator = mitk::CreateDistanceImageFromSurfaceFilter::New();
}

<|endoftext|>


<commit_before>/*
 * CUDArrays is a library for easy multi-GPU program development.
 *
 * The MIT License (MIT)
 *
 * Copyright (c) 2013-2015 Barcelona Supercomputing Center and
 *                         University of Illinois
 *
 *  Developed by: Javier Cabezas <javier.cabezas@gmail.com>
 *
 * Permission is hereby granted, free of charge, to any person obtaining a copy
 * of this software and associated documentation files (the "Software"), to deal
 * in the Software without restriction, including without limitation the rights
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 * copies of the Software, and to permit persons to whom the Software is
 * furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in
 * all copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
 * THE SOFTWARE. */

#pragma once
#ifndef CUDARRAYS_DETAIL_DYNARRAY_HELPERS_HPP_
#define CUDARRAYS_DETAIL_DYNARRAY_HELPERS_HPP_

#include <array>
#include <vector>

#include "../../storage.hpp"
#include "../../compute.hpp"

namespace cudarrays {

/**
 * Create a DimsComp-dimensional GPU grid the lowest order dimensions are maximized
 */
template <unsigned DimsComp>
static std::array<unsigned, DimsComp>
helper_distribution_get_gpu_grid(const cudarrays::compute_conf<DimsComp> &comp)
{
    std::array<unsigned, DimsComp> gpuGrid;

    // Check if we can map the arrayPartitionGrid on the GPUs
    std::vector<unsigned> factorsGpus = utils::get_factors(comp.procs);
    utils::sort(factorsGpus, std::greater<unsigned>());

#if 0
    if (factorsGPUs.size() < compPartDims)
        FATAL("CUDArrays cannot partition %u dimensions into %u GPUs", arrayPartDims, comp.procs);
#endif

    // Create the GPU grid
    unsigned j = 0;
    for (unsigned i : utils::make_range(DimsComp)) {
        if (comp.procs > 1) {
            unsigned partition = 1;
            if (comp.is_dim_part(i)) {
                ASSERT(j < factorsGpus.size());

                std::vector<unsigned>::iterator pos = factorsGpus.begin() + j;
                size_t inc = (j == 0)? factorsGpus.size() - comp.get_part_dims() + 1: 1;

                // DEBUG("Reshape> ALLOC: Collapsing%u: %zd:%zd", i, j, j + inc);
                partition = std::accumulate(pos, pos + inc, 1, std::multiplies<unsigned>());
                j += inc;
            }
            gpuGrid[i] = partition;
        } else {
            gpuGrid[i] = 1;
        }
    }

    return gpuGrid;
}

template <size_t DimsComp, size_t Dims>
static std::array<unsigned, Dims>
helper_distribution_get_array_grid(const std::array<unsigned, DimsComp> &gpuGrid,
                                   const std::array<int, Dims>          &arrayDimToCompDim)
{
    std::array<unsigned, Dims> ret;

    // Compute the array grid and the local sizes
    for (unsigned i : utils::make_range(Dims)) {
        int compDim = arrayDimToCompDim[i];

        unsigned partition = 1;
        if (compDim != DimInvalid) {
            partition = gpuGrid[compDim];
        } else {
            // TODO: REPLICATION
        }

        ret[i] = partition;
    }

    return ret;
}

template <size_t Dims>
static std::array<array_size_t, Dims>
helper_distribution_get_local_dims(const std::array<array_size_t, Dims> &dims,
                                   const std::array<unsigned, Dims>     &arrayGrid)
{
    std::array<array_size_t, Dims> ret;

    // Compute the array grid and the local sizes
    for (unsigned i : utils::make_range(Dims)) {
        // TODO: REPLICATION
        ret[i] = utils::div_ceil(dims[i], arrayGrid[i]);
    }

    return ret;
}

template <size_t Dims>
static array_size_t
helper_distribution_get_local_elems(const std::array<array_size_t, Dims> &dims,
                                    array_size_t boundary = 1)
{
    array_size_t ret;

    ret = utils::accumulate(dims, 1, std::multiplies<array_size_t>());
    // ... adjusting the tile size to VM SIZE
    ret = utils::round_next(ret, boundary);

    return ret;
}

template <size_t Dims>
static std::array<array_size_t, Dims - 1>
helper_distribution_get_local_offs(const std::array<array_size_t, Dims> &dims)
{
    std::array<array_size_t, Dims - 1> ret;

    array_size_t off = 1;
    for (ssize_t dim = ssize_t(Dims) - 2; dim >= 0; --dim) {
        off *= dims[dim + 1];
        ret[dim] = off;
    }

    return ret;
}

template <size_t Dims>
static std::array<array_size_t, Dims>
helper_distribution_get_intergpu_offs(array_size_t elemsLocal,
                                      const std::array<unsigned, Dims> &arrayGrid,
                                      const std::array<int, Dims>      &arrayDimToCompDim)
{
    std::array<array_size_t, Dims> ret;

    array_size_t off = 1;
    for (ssize_t dim = Dims - 1; dim >= 0; --dim) {
        if (arrayDimToCompDim[dim] != DimInvalid) {
            ret[dim] = off * elemsLocal;
            off *= arrayGrid[dim];
        } else {
            ret[dim] = 0;
        }
    }

    return ret;
}

template <size_t DimsComp>
static std::array<unsigned, DimsComp>
helper_distribution_gpu_get_offs(const std::array<unsigned, DimsComp> &gpuGrid)
{
    std::array<unsigned, DimsComp> ret;

    unsigned gridOff = 1;
    for (ssize_t dim = DimsComp - 1; dim >= 0; --dim) {
        ret[dim] = gridOff;
        if (dim < ssize_t(DimsComp)) {
            gridOff *= gpuGrid[dim];
        }
    }

    return ret;
}

template <size_t DimsComp, size_t Dims>
static std::array<unsigned, Dims>
helper_distribution_get_array_dim_to_gpus(const std::array<unsigned, DimsComp> &gpuGridOffs,
                                          const std::array<int, Dims>          &arrayDimToCompDim)
{
    std::array<unsigned, Dims> ret;

    for (unsigned dim : utils::make_range(Dims)) {
        int compDim = arrayDimToCompDim[dim];

        ret[dim] = (compDim != DimInvalid)? gpuGridOffs[compDim]: 0;
    }

    return ret;
}

}

#endif
<commit_msg>Add initializer for arrays in helpers<commit_after>/*
 * CUDArrays is a library for easy multi-GPU program development.
 *
 * The MIT License (MIT)
 *
 * Copyright (c) 2013-2015 Barcelona Supercomputing Center and
 *                         University of Illinois
 *
 *  Developed by: Javier Cabezas <javier.cabezas@gmail.com>
 *
 * Permission is hereby granted, free of charge, to any person obtaining a copy
 * of this software and associated documentation files (the "Software"), to deal
 * in the Software without restriction, including without limitation the rights
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 * copies of the Software, and to permit persons to whom the Software is
 * furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in
 * all copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
 * THE SOFTWARE. */

#pragma once
#ifndef CUDARRAYS_DETAIL_DYNARRAY_HELPERS_HPP_
#define CUDARRAYS_DETAIL_DYNARRAY_HELPERS_HPP_

#include <array>
#include <vector>

#include "../../storage.hpp"
#include "../../compute.hpp"

namespace cudarrays {

/**
 * Create a DimsComp-dimensional GPU grid the lowest order dimensions are maximized
 */
template <unsigned DimsComp>
static std::array<unsigned, DimsComp>
helper_distribution_get_gpu_grid(const cudarrays::compute_conf<DimsComp> &comp)
{
    std::array<unsigned, DimsComp> gpuGrid = {{}};

    // Check if we can map the arrayPartitionGrid on the GPUs
    std::vector<unsigned> factorsGpus = utils::get_factors(comp.procs);
    utils::sort(factorsGpus, std::greater<unsigned>());

#if 0
    if (factorsGPUs.size() < compPartDims)
        FATAL("CUDArrays cannot partition %u dimensions into %u GPUs", arrayPartDims, comp.procs);
#endif

    // Create the GPU grid
    unsigned j = 0;
    for (unsigned i : utils::make_range(DimsComp)) {
        if (comp.procs > 1) {
            unsigned partition = 1;
            if (comp.is_dim_part(i)) {
                ASSERT(j < factorsGpus.size());

                std::vector<unsigned>::iterator pos = factorsGpus.begin() + j;
                size_t inc = (j == 0)? factorsGpus.size() - comp.get_part_dims() + 1: 1;

                // DEBUG("Reshape> ALLOC: Collapsing%u: %zd:%zd", i, j, j + inc);
                partition = std::accumulate(pos, pos + inc, 1, std::multiplies<unsigned>());
                j += inc;
            }
            gpuGrid[i] = partition;
        } else {
            gpuGrid[i] = 1;
        }
    }

    return gpuGrid;
}

template <size_t DimsComp, size_t Dims>
static std::array<unsigned, Dims>
helper_distribution_get_array_grid(const std::array<unsigned, DimsComp> &gpuGrid,
                                   const std::array<int, Dims>          &arrayDimToCompDim)
{
    std::array<unsigned, Dims> ret{{}};

    // Compute the array grid and the local sizes
    for (unsigned i : utils::make_range(Dims)) {
        int compDim = arrayDimToCompDim[i];

        unsigned partition = 1;
        if (compDim != DimInvalid) {
            partition = gpuGrid[compDim];
        } else {
            // TODO: REPLICATION
        }

        ret[i] = partition;
    }

    return ret;
}

template <size_t Dims>
static std::array<array_size_t, Dims>
helper_distribution_get_local_dims(const std::array<array_size_t, Dims> &dims,
                                   const std::array<unsigned, Dims>     &arrayGrid)
{
    std::array<array_size_t, Dims> ret{{}};

    // Compute the array grid and the local sizes
    for (unsigned i : utils::make_range(Dims)) {
        // TODO: REPLICATION
        ret[i] = utils::div_ceil(dims[i], arrayGrid[i]);
    }

    return ret;
}

template <size_t Dims>
static array_size_t
helper_distribution_get_local_elems(const std::array<array_size_t, Dims> &dims,
                                    array_size_t boundary = 1)
{
    array_size_t ret;

    ret = utils::accumulate(dims, 1, std::multiplies<array_size_t>());
    // ... adjusting the tile size to VM SIZE
    ret = utils::round_next(ret, boundary);

    return ret;
}

template <size_t Dims>
static std::array<array_size_t, Dims - 1>
helper_distribution_get_local_offs(const std::array<array_size_t, Dims> &dims)
{
    std::array<array_size_t, Dims - 1> ret{{}};

    array_size_t off = 1;
    for (ssize_t dim = ssize_t(Dims) - 2; dim >= 0; --dim) {
        off *= dims[dim + 1];
        ret[dim] = off;
    }

    return ret;
}

template <size_t Dims>
static std::array<array_size_t, Dims>
helper_distribution_get_intergpu_offs(array_size_t elemsLocal,
                                      const std::array<unsigned, Dims> &arrayGrid,
                                      const std::array<int, Dims>      &arrayDimToCompDim)
{
    std::array<array_size_t, Dims> ret{{}};

    array_size_t off = 1;
    for (ssize_t dim = Dims - 1; dim >= 0; --dim) {
        if (arrayDimToCompDim[dim] != DimInvalid) {
            ret[dim] = off * elemsLocal;
            off *= arrayGrid[dim];
        } else {
            ret[dim] = 0;
        }
    }

    return ret;
}

template <size_t DimsComp>
static std::array<unsigned, DimsComp>
helper_distribution_gpu_get_offs(const std::array<unsigned, DimsComp> &gpuGrid)
{
    std::array<unsigned, DimsComp> ret{{}};

    unsigned gridOff = 1;
    for (ssize_t dim = DimsComp - 1; dim >= 0; --dim) {
        ret[dim] = gridOff;
        if (dim < ssize_t(DimsComp)) {
            gridOff *= gpuGrid[dim];
        }
    }

    return ret;
}

template <size_t DimsComp, size_t Dims>
static std::array<unsigned, Dims>
helper_distribution_get_array_dim_to_gpus(const std::array<unsigned, DimsComp> &gpuGridOffs,
                                          const std::array<int, Dims>          &arrayDimToCompDim)
{
    std::array<unsigned, Dims> ret{{}};

    for (unsigned dim : utils::make_range(Dims)) {
        int compDim = arrayDimToCompDim[dim];

        ret[dim] = (compDim != DimInvalid)? gpuGridOffs[compDim]: 0;
    }

    return ret;
}

}

#endif
<|endoftext|>


<commit_before>// ///////////////////////////////////////////////////////////////////////////
// tenh/conceptual/conceptualinheritancegraph.hpp by Vector Dods, created 2013/09/12
// Copyright Leap Motion Inc.
// ///////////////////////////////////////////////////////////////////////////

#ifndef TENH_CONCEPTUAL_CONCEPTUALINHERITANCEGRAPH_HPP_
#define TENH_CONCEPTUAL_CONCEPTUALINHERITANCEGRAPH_HPP_

#include "tenh/core.hpp"

#include <cassert>
#include <map>
#include <ostream>
#include <set>
#include <sstream>
#include <string>

#include "tenh/conceptual/concept.hpp"

namespace Tenh {

struct Graph
{
    struct Node
    {
        std::string m_shortified_name;
        std::string m_full_name;

        Node (std::string const &shortified_name, std::string const &full_name)
            :
            m_shortified_name(shortified_name),
            m_full_name(full_name)
        {
            assert(!m_shortified_name.empty());
            assert(!m_full_name.empty());
        }

        bool operator == (Node const &r) const
        {
            return this->m_shortified_name == r.m_shortified_name && this->m_full_name == r.m_full_name;
        }
        bool operator < (Node const &r) const
        {
            return this->m_shortified_name < r.m_shortified_name
                   ||
                   (this->m_shortified_name == r.m_shortified_name && this->m_full_name < r.m_full_name);
        }

        struct Order
        {
            bool operator () (Node const &l, Node const &r)
            {
                return l < r;
            }
        };
    };

    struct Edge
    {
        Node m_source;
        Node m_target;

        Edge (Node const &source, Node const &target) : m_source(source), m_target(target) { }

        bool operator < (Edge const &r) const
        {
            return this->m_source < r.m_source
                   ||
                   (this->m_source == r.m_source && this->m_target < r.m_target);
        }

        struct Order
        {
            bool operator () (Edge const &l, Edge const &r)
            {
                return l < r;
            }
        };
    };

    typedef std::set<Node> Nodes;
    typedef std::set<Edge> Edges;

    // constructs an empty graph
    Graph () { }

    void clear () { m_nodes.clear(); m_edges.clear(); }

    void add_node (Node const &node) { m_nodes.insert(node); }
    void add_edge (Node const &source, Node const &target)
    {
        assert(m_nodes.find(source) != m_nodes.end() && "the source node must already be in the graph");
        assert(m_nodes.find(target) != m_nodes.end() && "the target node must already be in the graph");
        m_edges.insert(Edge(source, target));
    }

    Nodes const &nodes () const { return m_nodes; }
    Edges const &edges () const { return m_edges; }

    Edges edges_having_source_node (Node const &node) const
    {
        Edges retval;
        for (Edges::const_iterator it = m_edges.begin(), it_end = m_edges.end(); it != it_end; ++it)
        {
            Edge const &edge = *it;
            if (edge.m_source == node)
                retval.insert(edge);
        }
        return retval;
    }
    Edges edges_having_target_node (Node const &node) const
    {
        Edges retval;
        for (Edges::const_iterator it = m_edges.begin(), it_end = m_edges.end(); it != it_end; ++it)
        {
            Edge const &edge = *it;
            if (edge.m_target == node)
                retval.insert(edge);
        }
        return retval;
    }

    void print_as_dot_graph (std::ostream &out) const
    {
        // have to use identifiers instead of the full strings for the node names in dot,
        // so this part is to construct a map from nodes to identifiers (and back)
        typedef std::map<Node,std::string> NodeIdentifierMap;
        NodeIdentifierMap node_identifier_map;
        Uint32 id_number = 0;
        for (Nodes::const_iterator it = m_nodes.begin(), it_end = m_nodes.end(); it != it_end; ++it)
        {
            Node const &n = *it;
            std::string id(FORMAT("id" << id_number++));
            node_identifier_map[n] = id;
        }

        // generate the dot graph
        out << "digraph {\n";
        for (Nodes::const_iterator it = m_nodes.begin(), it_end = m_nodes.end(); it != it_end; ++it)
        {
            Node const &n = *it;
            out << "    " << node_identifier_map[n] << " [label=\"";
            print_string_with_newlines_as_char_literals(out, n.m_shortified_name);
            out << "\", fontname=\"courier\", labeljust=\"l\", shape=box];\n";
        }
        out << '\n';
        for (Edges::const_iterator it = m_edges.begin(), it_end = m_edges.end(); it != it_end; ++it)
        {
            Edge const &e = *it;
            out << "    " << node_identifier_map[e.m_source] << " -> " << node_identifier_map[e.m_target] << ";\n";
        }
        out << "}\n";
    }

private:

    static void print_string_with_newlines_as_char_literals (std::ostream &out, std::string const &s)
    {
        for (std::string::const_iterator it = s.begin(), it_end = s.end(); it != it_end; ++it)
        {
            char const &c = *it;
            if (c == '\n')
                out << "\\n";
            else
                out << c;
        }
    }

    Nodes m_nodes;
    Edges m_edges;
};

std::ostream &operator << (std::ostream &out, Graph::Node const &n)
{
    if (n.m_shortified_name == n.m_full_name)
        return out << "Node(" << n.m_full_name << ')';
    else
        return out << "Node(" << n.m_shortified_name << ',' << n.m_full_name << ')';
}

std::ostream &operator << (std::ostream &out, Graph::Edge const &e)
{
    return out << "Edge(" << e.m_source << " -> " << e.m_target << ')';
}

std::ostream &operator << (std::ostream &out, Graph const &g)
{
    out << "Graph(\n";
    for (Graph::Nodes::const_iterator it = g.nodes().begin(), it_end = g.nodes().end(); it != it_end; ++it)
    {
        Graph::Node const &n = *it;
        out << '\t' << n << '\n';
    }
    out << '\n';
    for (Graph::Edges::const_iterator it = g.edges().begin(), it_end = g.edges().end(); it != it_end; ++it)
    {
        Graph::Edge const &e = *it;
        out << '\t' << e << '\n';
    }
    return out << ")\n";
}

template <Uint32 SHORTIFY_DEPTH_, typename Concept_, typename HeadType_, typename BodyTypeList_>
void add_parent_concept_type_list_to_graph_recursive (Concept_ const &concept, TypeList_t<HeadType_,BodyTypeList_> const &parent_concept_type_list, Graph &g)
{
    // add the parent nodes and edges connecting concept to them
    Graph::Node concept_node(FORMAT((Pretty<TypeStringOf_t<Concept_>,SHORTIFY_DEPTH_>())),
                             FORMAT((Pretty<TypeStringOf_t<Concept_>,0>())));
    assert(g.nodes().find(concept_node) != g.nodes().end());
    Graph::Node parent_node(FORMAT((Pretty<TypeStringOf_t<HeadType_>,SHORTIFY_DEPTH_>())),
                            FORMAT((Pretty<TypeStringOf_t<HeadType_>,0>())));
    g.add_node(parent_node);
    g.add_edge(concept_node, parent_node);
    add_parent_concept_type_list_to_graph_recursive<SHORTIFY_DEPTH_>(concept, BodyTypeList_(), g);

    // call this function recursively on each parent
    add_parent_concept_type_list_to_graph_recursive<SHORTIFY_DEPTH_>(HeadType_(), typename HeadType_::ParentTypeList(), g);
}

template <Uint32 SHORTIFY_DEPTH_, typename Concept_>
void add_parent_concept_type_list_to_graph_recursive (Concept_ const &, EmptyTypeList const &, Graph &g)
{
    // nothing to add
}

template <Uint32 SHORTIFY_DEPTH_, typename Concept_>
void add_concept_hierarchy_to_graph (Concept_ const &root, Graph &g)
{
    Graph::Node n(FORMAT((Pretty<TypeStringOf_t<Concept_>,SHORTIFY_DEPTH_>())),
                  FORMAT((Pretty<TypeStringOf_t<Concept_>,0>())));
    g.add_node(n);
    add_parent_concept_type_list_to_graph_recursive<SHORTIFY_DEPTH_>(root, typename Concept_::ParentTypeList(), g);
}

} // end of namespace Tenh

#endif // TENH_CONCEPTUAL_CONCEPTUALINHERITANCEGRAPH_HPP_<commit_msg>Fixed an ordering issue in the definition of a templatized conceptual hierarchy graphing function, which GCC was complaining about.<commit_after>// ///////////////////////////////////////////////////////////////////////////
// tenh/conceptual/conceptualinheritancegraph.hpp by Vector Dods, created 2013/09/12
// Copyright Leap Motion Inc.
// ///////////////////////////////////////////////////////////////////////////

#ifndef TENH_CONCEPTUAL_CONCEPTUALINHERITANCEGRAPH_HPP_
#define TENH_CONCEPTUAL_CONCEPTUALINHERITANCEGRAPH_HPP_

#include "tenh/core.hpp"

#include <cassert>
#include <map>
#include <ostream>
#include <set>
#include <sstream>
#include <string>

#include "tenh/conceptual/concept.hpp"

namespace Tenh {

struct Graph
{
    struct Node
    {
        std::string m_shortified_name;
        std::string m_full_name;

        Node (std::string const &shortified_name, std::string const &full_name)
            :
            m_shortified_name(shortified_name),
            m_full_name(full_name)
        {
            assert(!m_shortified_name.empty());
            assert(!m_full_name.empty());
        }

        bool operator == (Node const &r) const
        {
            return this->m_shortified_name == r.m_shortified_name && this->m_full_name == r.m_full_name;
        }
        bool operator < (Node const &r) const
        {
            return this->m_shortified_name < r.m_shortified_name
                   ||
                   (this->m_shortified_name == r.m_shortified_name && this->m_full_name < r.m_full_name);
        }

        struct Order
        {
            bool operator () (Node const &l, Node const &r)
            {
                return l < r;
            }
        };
    };

    struct Edge
    {
        Node m_source;
        Node m_target;

        Edge (Node const &source, Node const &target) : m_source(source), m_target(target) { }

        bool operator < (Edge const &r) const
        {
            return this->m_source < r.m_source
                   ||
                   (this->m_source == r.m_source && this->m_target < r.m_target);
        }

        struct Order
        {
            bool operator () (Edge const &l, Edge const &r)
            {
                return l < r;
            }
        };
    };

    typedef std::set<Node> Nodes;
    typedef std::set<Edge> Edges;

    // constructs an empty graph
    Graph () { }

    void clear () { m_nodes.clear(); m_edges.clear(); }

    void add_node (Node const &node) { m_nodes.insert(node); }
    void add_edge (Node const &source, Node const &target)
    {
        assert(m_nodes.find(source) != m_nodes.end() && "the source node must already be in the graph");
        assert(m_nodes.find(target) != m_nodes.end() && "the target node must already be in the graph");
        m_edges.insert(Edge(source, target));
    }

    Nodes const &nodes () const { return m_nodes; }
    Edges const &edges () const { return m_edges; }

    Edges edges_having_source_node (Node const &node) const
    {
        Edges retval;
        for (Edges::const_iterator it = m_edges.begin(), it_end = m_edges.end(); it != it_end; ++it)
        {
            Edge const &edge = *it;
            if (edge.m_source == node)
                retval.insert(edge);
        }
        return retval;
    }
    Edges edges_having_target_node (Node const &node) const
    {
        Edges retval;
        for (Edges::const_iterator it = m_edges.begin(), it_end = m_edges.end(); it != it_end; ++it)
        {
            Edge const &edge = *it;
            if (edge.m_target == node)
                retval.insert(edge);
        }
        return retval;
    }

    void print_as_dot_graph (std::ostream &out) const
    {
        // have to use identifiers instead of the full strings for the node names in dot,
        // so this part is to construct a map from nodes to identifiers (and back)
        typedef std::map<Node,std::string> NodeIdentifierMap;
        NodeIdentifierMap node_identifier_map;
        Uint32 id_number = 0;
        for (Nodes::const_iterator it = m_nodes.begin(), it_end = m_nodes.end(); it != it_end; ++it)
        {
            Node const &n = *it;
            std::string id(FORMAT("id" << id_number++));
            node_identifier_map[n] = id;
        }

        // generate the dot graph
        out << "digraph {\n";
        for (Nodes::const_iterator it = m_nodes.begin(), it_end = m_nodes.end(); it != it_end; ++it)
        {
            Node const &n = *it;
            out << "    " << node_identifier_map[n] << " [label=\"";
            print_string_with_newlines_as_char_literals(out, n.m_shortified_name);
            out << "\", fontname=\"courier\", labeljust=\"l\", shape=box];\n";
        }
        out << '\n';
        for (Edges::const_iterator it = m_edges.begin(), it_end = m_edges.end(); it != it_end; ++it)
        {
            Edge const &e = *it;
            out << "    " << node_identifier_map[e.m_source] << " -> " << node_identifier_map[e.m_target] << ";\n";
        }
        out << "}\n";
    }

private:

    static void print_string_with_newlines_as_char_literals (std::ostream &out, std::string const &s)
    {
        for (std::string::const_iterator it = s.begin(), it_end = s.end(); it != it_end; ++it)
        {
            char const &c = *it;
            if (c == '\n')
                out << "\\n";
            else
                out << c;
        }
    }

    Nodes m_nodes;
    Edges m_edges;
};

std::ostream &operator << (std::ostream &out, Graph::Node const &n)
{
    if (n.m_shortified_name == n.m_full_name)
        return out << "Node(" << n.m_full_name << ')';
    else
        return out << "Node(" << n.m_shortified_name << ',' << n.m_full_name << ')';
}

std::ostream &operator << (std::ostream &out, Graph::Edge const &e)
{
    return out << "Edge(" << e.m_source << " -> " << e.m_target << ')';
}

std::ostream &operator << (std::ostream &out, Graph const &g)
{
    out << "Graph(\n";
    for (Graph::Nodes::const_iterator it = g.nodes().begin(), it_end = g.nodes().end(); it != it_end; ++it)
    {
        Graph::Node const &n = *it;
        out << '\t' << n << '\n';
    }
    out << '\n';
    for (Graph::Edges::const_iterator it = g.edges().begin(), it_end = g.edges().end(); it != it_end; ++it)
    {
        Graph::Edge const &e = *it;
        out << '\t' << e << '\n';
    }
    return out << ")\n";
}

// base case
template <Uint32 SHORTIFY_DEPTH_, typename Concept_>
void add_parent_concept_type_list_to_graph_recursive (Concept_ const &, EmptyTypeList const &, Graph &g)
{
    // nothing to add
}

template <Uint32 SHORTIFY_DEPTH_, typename Concept_, typename HeadType_, typename BodyTypeList_>
void add_parent_concept_type_list_to_graph_recursive (
    Concept_ const &concept,
    TypeList_t<HeadType_,BodyTypeList_> const &parent_concept_type_list,
    Graph &g)
{
    // add the parent nodes and edges connecting concept to them
    Graph::Node concept_node(FORMAT((Pretty<TypeStringOf_t<Concept_>,SHORTIFY_DEPTH_>())),
                             FORMAT((Pretty<TypeStringOf_t<Concept_>,0>())));
    assert(g.nodes().find(concept_node) != g.nodes().end());
    Graph::Node parent_node(FORMAT((Pretty<TypeStringOf_t<HeadType_>,SHORTIFY_DEPTH_>())),
                            FORMAT((Pretty<TypeStringOf_t<HeadType_>,0>())));
    g.add_node(parent_node);
    g.add_edge(concept_node, parent_node);
    add_parent_concept_type_list_to_graph_recursive<SHORTIFY_DEPTH_>(concept, BodyTypeList_(), g);

    // call this function recursively on each parent
    add_parent_concept_type_list_to_graph_recursive<SHORTIFY_DEPTH_>(HeadType_(), typename HeadType_::ParentTypeList(), g);
}

template <Uint32 SHORTIFY_DEPTH_, typename Concept_>
void add_concept_hierarchy_to_graph (Concept_ const &root, Graph &g)
{
    Graph::Node n(FORMAT((Pretty<TypeStringOf_t<Concept_>,SHORTIFY_DEPTH_>())),
                  FORMAT((Pretty<TypeStringOf_t<Concept_>,0>())));
    g.add_node(n);
    add_parent_concept_type_list_to_graph_recursive<SHORTIFY_DEPTH_>(root, typename Concept_::ParentTypeList(), g);
}

} // end of namespace Tenh

#endif // TENH_CONCEPTUAL_CONCEPTUALINHERITANCEGRAPH_HPP_<|endoftext|>


<commit_before>#pragma once

// std
#include <cstdint>
#include <unordered_map>

// project
#include "depthai-shared/common/UsbSpeed.hpp"
#include "depthai-shared/common/optional.hpp"
#include "depthai-shared/device/BoardConfig.hpp"
#include "depthai-shared/utility/Serialization.hpp"
#include "depthai-shared/xlink/XLinkConstants.hpp"

namespace dai {

constexpr static uint32_t BOARD_CONFIG_MAGIC1 = 0x78010000U;
constexpr static uint32_t BOARD_CONFIG_MAGIC2 = 0x21ea17e6U;

struct BoardConfig {
    // USB related config
    struct USB {
        uint16_t vid = 0x03e7, pid = 0xf63b;
        uint16_t flashBootedVid = 0x03e7, flashBootedPid = 0xf63d;
        UsbSpeed maxSpeed = UsbSpeed::SUPER;
    };

    USB usb;

    // Watchdog config
    tl::optional<uint32_t> watchdogTimeoutMs;
    tl::optional<uint32_t> watchdogInitialDelayMs;

    // GPIO config
    struct GPIO {
        enum Mode : std::int8_t { ALT_MODE_0 = 0, ALT_MODE_1, ALT_MODE_2, ALT_MODE_3, ALT_MODE_4, ALT_MODE_5, ALT_MODE_6, DIRECT };
        Mode mode = Mode::DIRECT;
        enum Direction : std::int8_t { INPUT = 0, OUTPUT = 1 };
        Direction direction = Direction::INPUT;
        enum Level : std::int8_t { LOW = 0, HIGH = 1 };
        Level level = Level::LOW;
        enum Pull : std::int8_t { NO_PULL = 0, PULL_UP = 1, PULL_DOWN = 2, BUS_KEEPER = 3 };
        Pull pull = Pull::NO_PULL;
        /// Drive strength in mA (2, 4, 8 and 12mA)
        std::int8_t drive = 0;
        bool schmitt = false, slewFast = false;
        GPIO() = default;
        GPIO(Direction direction) : direction(direction) {}
        GPIO(Direction direction, Level level) : direction(direction), level(level) {}
        GPIO(Direction direction, Level level, Pull pull) : direction(direction), level(level), pull(pull) {}
        GPIO(Direction direction, Mode mode) : mode(mode), direction(direction) {}
        GPIO(Direction direction, Mode mode, Pull pull) : mode(mode), direction(direction), pull(pull) {}
    };
    std::unordered_map<std::int8_t, GPIO> gpio;

    // Uart config

    /// UART instance config
    struct UART {
        // TBD
        // std::int8_t tx, rx;
        std::int8_t tmp;
    };
    /// UART instance map
    std::unordered_map<std::int8_t, UART> uart;
};

DEPTHAI_SERIALIZE_EXT(BoardConfig::USB, vid, pid, flashBootedVid, flashBootedPid, maxSpeed);
DEPTHAI_SERIALIZE_EXT(BoardConfig::GPIO, mode, direction, level, pull, drive, schmitt, slewFast);
DEPTHAI_SERIALIZE_EXT(BoardConfig::UART, tmp);
DEPTHAI_SERIALIZE_EXT(BoardConfig, usb, watchdogTimeoutMs, watchdogInitialDelayMs, gpio, uart);

}  // namespace dai
<commit_msg>Added GPIO drive as enum<commit_after>#pragma once

// std
#include <cstdint>
#include <unordered_map>

// project
#include "depthai-shared/common/UsbSpeed.hpp"
#include "depthai-shared/common/optional.hpp"
#include "depthai-shared/device/BoardConfig.hpp"
#include "depthai-shared/utility/Serialization.hpp"
#include "depthai-shared/xlink/XLinkConstants.hpp"

namespace dai {

constexpr static uint32_t BOARD_CONFIG_MAGIC1 = 0x78010000U;
constexpr static uint32_t BOARD_CONFIG_MAGIC2 = 0x21ea17e6U;

struct BoardConfig {
    // USB related config
    struct USB {
        uint16_t vid = 0x03e7, pid = 0xf63b;
        uint16_t flashBootedVid = 0x03e7, flashBootedPid = 0xf63d;
        UsbSpeed maxSpeed = UsbSpeed::SUPER;
    };

    USB usb;

    // Watchdog config
    tl::optional<uint32_t> watchdogTimeoutMs;
    tl::optional<uint32_t> watchdogInitialDelayMs;

    // GPIO config
    struct GPIO {
        enum Mode : std::int8_t { ALT_MODE_0 = 0, ALT_MODE_1, ALT_MODE_2, ALT_MODE_3, ALT_MODE_4, ALT_MODE_5, ALT_MODE_6, DIRECT };
        Mode mode = Mode::DIRECT;
        enum Direction : std::int8_t { INPUT = 0, OUTPUT = 1 };
        Direction direction = Direction::INPUT;
        enum Level : std::int8_t { LOW = 0, HIGH = 1 };
        Level level = Level::LOW;
        enum Pull : std::int8_t { NO_PULL = 0, PULL_UP = 1, PULL_DOWN = 2, BUS_KEEPER = 3 };
        Pull pull = Pull::NO_PULL;
        /// Drive strength in mA (2, 4, 8 and 12mA)
        enum Drive : std::int8_t { MA_2 = 2, MA_4 = 4, MA_8 = 8, MA_12 = 12 };
        Drive drive = MA_2;
        bool schmitt = false, slewFast = false;
        GPIO() = default;
        GPIO(Direction direction) : direction(direction) {}
        GPIO(Direction direction, Level level) : direction(direction), level(level) {}
        GPIO(Direction direction, Level level, Pull pull) : direction(direction), level(level), pull(pull) {}
        GPIO(Direction direction, Mode mode) : mode(mode), direction(direction) {}
        GPIO(Direction direction, Mode mode, Pull pull) : mode(mode), direction(direction), pull(pull) {}
    };
    std::unordered_map<std::int8_t, GPIO> gpio;

    // Uart config

    /// UART instance config
    struct UART {
        // TBD
        // std::int8_t tx, rx;
        std::int8_t tmp;
    };
    /// UART instance map
    std::unordered_map<std::int8_t, UART> uart;
};

DEPTHAI_SERIALIZE_EXT(BoardConfig::USB, vid, pid, flashBootedVid, flashBootedPid, maxSpeed);
DEPTHAI_SERIALIZE_EXT(BoardConfig::GPIO, mode, direction, level, pull, drive, schmitt, slewFast);
DEPTHAI_SERIALIZE_EXT(BoardConfig::UART, tmp);
DEPTHAI_SERIALIZE_EXT(BoardConfig, usb, watchdogTimeoutMs, watchdogInitialDelayMs, gpio, uart);

}  // namespace dai
<|endoftext|>