<commit_before>#include "VoreealEditorPrivatePCH.h"
#include "BasicVolumeEditorViewportClient.h"

#include "SceneViewport.h"
#include "PreviewScene.h"
#include "ScopedTransaction.h"
#include "Runtime/Engine/Public/ComponentReregisterContext.h"

#include "AssetToolsModule.h"
#include "ContentBrowserModule.h"
#include "AssetRegistryModule.h"
#include "CanvasTypes.h"
#include "CanvasItem.h"

#include "SEditorViewport.h"
#include "SNotificationList.h"
#include "NotificationManager.h"

#include "BasicVolumeEditorSettings.h"

#define LOCTEXT_NAMESPACE "VoreealEditor"

FBasicVolumeEditorViewportClient::FBasicVolumeEditorViewportClient(TWeakPtr<FBasicVolumeEditor> InEditor, TWeakPtr<class SEditorViewport> InEditorViewportPtr)
	: CurrentMode(EBasicVolumeEditorMode::ViewMode)
	, EditorPtr(InEditor)
	, EditorViewportPtr(InEditorViewportPtr)
{
	check(EditorPtr.IsValid() && EditorViewportPtr.IsValid());

	Widget->SetUsesEditorModeTools(ModeTools);

	PreviewScene = &OwnedPreviewScene;
	((FAssetEditorModeManager*)ModeTools)->SetPreviewScene(PreviewScene);

	SetRealtime(true);

	bManipulating = false;
	bManipulationDirtiedSomething = false;
	ScopedTransaction = nullptr;

	bShowOctree = false;
	bShowSockets = true;
	bShowPivot = true;

	DrawHelper.bDrawGrid = GetDefault<UBasicVolumeEditorSettings>()->bShowGridByDefault;

	EngineShowFlags.DisableAdvancedFeatures();
	EngineShowFlags.SetCompositeEditorPrimitives(true);

	// Create a render component for the volume being edited
	{
		RenderVolumeComponent = NewObject<UBasicVolumeComponent>();
		UBasicVolume* Volume = GetVolumeBeingEdited();
		RenderVolumeComponent->SetBasicVolume(Volume);

		PreviewScene->AddComponent(RenderVolumeComponent, FTransform::Identity);
	}
}

void FBasicVolumeEditorViewportClient::ActivateEditMode()
{
	ModeTools->SetWidgetMode(FWidget::WM_Translate);
}

#pragma region // Begin Show Flags
void FBasicVolumeEditorViewportClient::SetShowOctree(bool bShow)
{
	bShowOctree = !bShowOctree;
	Invalidate();
}

void FBasicVolumeEditorViewportClient::ToggleShowOctree()
{
	bShowOctree = !bShowOctree;
	Invalidate();
}

bool FBasicVolumeEditorViewportClient::IsSetShowOctreeChecked() const
{
	return bShowOctree;
}

void FBasicVolumeEditorViewportClient::ToggleShowSockets()
{
	bShowSockets = !bShowSockets;
	Invalidate();
}

bool FBasicVolumeEditorViewportClient::IsShowSocketsChecked() const
{
	return bShowSockets;
}

void FBasicVolumeEditorViewportClient::ToggleShowPivot()
{
	bShowPivot = !bShowPivot;
	Invalidate();
}

bool FBasicVolumeEditorViewportClient::IsShowPivotChecked() const
{
	return bShowPivot;
}
#pragma endregion

void FBasicVolumeEditorViewportClient::EnterViewMode()
{
	InternalActivateNewMode(EBasicVolumeEditorMode::ViewMode);
}

void FBasicVolumeEditorViewportClient::EnterEditMode()
{
	InternalActivateNewMode(EBasicVolumeEditorMode::EditMode);
}

bool FBasicVolumeEditorViewportClient::IsInViewMode() const
{
	return CurrentMode == EBasicVolumeEditorMode::ViewMode;
}

bool FBasicVolumeEditorViewportClient::IsInEditMode() const
{
	return CurrentMode == EBasicVolumeEditorMode::EditMode;
}

void FBasicVolumeEditorViewportClient::DrawCanvas(FViewport& pViewport, FSceneView& View, FCanvas& Canvas)
{
	const bool bIsHitTesting = Canvas.IsHitTesting();
	if (!bIsHitTesting)
	{
		Canvas.SetHitProxy(nullptr);
	}

	if (!EditorPtr.IsValid())
	{
		return;
	}

	UBasicVolume* Volume = GetVolumeBeingEdited();

	switch (CurrentMode)
	{
	default:
	case EBasicVolumeEditorMode::ViewMode:
		break;
	case EBasicVolumeEditorMode::EditMode:
		break;
	}

	//if (bShowSockets && !IsInSourceRegionEditMode())
	//{
	//	FSpriteGeometryEditMode* GeometryEditMode = ModeTools->GetActiveModeTyped<FSpriteGeometryEditMode>(FSpriteGeometryEditMode::EM_SpriteGeometry);
	//	FSocketEditingHelper::DrawSocketNames(GeometryEditMode, RenderVolumeComponent, Viewport, View, Canvas);
	//}

	FEditorViewportClient::DrawCanvas(pViewport, View, Canvas);
}

void FBasicVolumeEditorViewportClient::Draw(const FSceneView* View, FPrimitiveDrawInterface* PDI)
{
	FEditorViewportClient::Draw(View, PDI);

	//// We don't draw the pivot when showing the source region
	//// The pivot may be outside the actual texture bounds there
	//if (bShowPivot && !bShowSourceTexture && !IsInSourceRegionEditMode())
	//{
	//	const bool bCanSelectPivot = false;
	//	const bool bHitTestingForPivot = PDI->IsHitTesting() && bCanSelectPivot;
	//	FUnrealEdUtils::DrawWidget(View, PDI, RenderSpriteComponent->ComponentToWorld.ToMatrixWithScale(), 0, 0, EAxisList::XZ, EWidgetMovementMode::WMM_Translate, bHitTestingForPivot);
	//}

	//if (bShowSockets && !IsInSourceRegionEditMode())
	//{
	//	FSpriteGeometryEditMode* GeometryEditMode = ModeTools->GetActiveModeTyped<FSpriteGeometryEditMode>(FSpriteGeometryEditMode::EM_SpriteGeometry);
	//	FSocketEditingHelper::DrawSockets(GeometryEditMode, RenderSpriteComponent, View, PDI);
	//}
}

FBox FBasicVolumeEditorViewportClient::GetDesiredFocusBounds() const
{
	UBasicVolumeComponent* ComponentToFocusOn = RenderVolumeComponent;
	return ComponentToFocusOn->Bounds.GetBox();
}

void FBasicVolumeEditorViewportClient::Tick(float DeltaSeconds)
{
	if (UBasicVolume* Volume = GetVolumeBeingEdited())
	{

	}

	FVoreealEditorViewportClient::Tick(DeltaSeconds);

	// Draw the octree
	if (bShowOctree && RenderVolumeComponent)
	{
		RenderVolumeComponent->DrawDebugOctree(FLinearColor::Red, 0, 1.0f);
	}

	if (!GIntraFrameDebuggingGameThread)
	{
		OwnedPreviewScene.GetWorld()->Tick(LEVELTICK_All, DeltaSeconds);
	}
}

void FBasicVolumeEditorViewportClient::ProcessClick(FSceneView& View, HHitProxy* HitProxy, FKey Key, EInputEvent Event, uint32 HitX, uint32 HitY)
{
	const FViewportClick Click(&View, this, Key, Event, HitX, HitY);
	const bool bIsCtrlKeyDown = Viewport->KeyState(EKeys::LeftControl) || Viewport->KeyState(EKeys::RightControl);
	const bool bIsShiftKeyDown = Viewport->KeyState(EKeys::LeftShift) || Viewport->KeyState(EKeys::RightShift);
	const bool bIsAltKeyDown = Viewport->KeyState(EKeys::LeftAlt) || Viewport->KeyState(EKeys::RightAlt);
	bool bHandled = false;

	//HSpriteSelectableObjectHitProxy* SelectedItemProxy = HitProxyCast<HSpriteSelectableObjectHitProxy>(HitProxy);
	//
	//if (IsInSourceRegionEditMode())
	//{
	//	if ((Event == EInputEvent::IE_DoubleClick) && (Key == EKeys::LeftMouseButton))
	//	{
	//		FVector4 WorldPoint = View.PixelToWorld(HitX, HitY, 0);
	//		UPaperSprite* Sprite = GetSpriteBeingEdited();
	//		FVector2D TexturePoint = SourceTextureViewComponent->GetSprite()->ConvertWorldSpaceToTextureSpace(WorldPoint);
	//		if (bIsCtrlKeyDown)
	//		{
	//			const FVector2D StartingUV = Sprite->GetSourceUV();
	//			const FVector2D StartingSize = Sprite->GetSourceSize();
	//
	//			if (UPaperSprite* NewSprite = CreateNewSprite(FIntPoint((int32)StartingUV.X, (int32)StartingUV.Y), FIntPoint((int32)StartingSize.X, (int32)StartingSize.Y)))
	//			{
	//				NewSprite->ExtractSourceRegionFromTexturePoint(TexturePoint);
	//				bHandled = true;
	//			}
	//		}
	//		else
	//		{
	//			Sprite->ExtractSourceRegionFromTexturePoint(TexturePoint);
	//			bHandled = true;
	//		}
	//	}
	//	else if ((Event == EInputEvent::IE_Released) && (Key == EKeys::LeftMouseButton))
	//	{
	//		FVector4 WorldPoint = View.PixelToWorld(HitX, HitY, 0);
	//		FVector2D TexturePoint = SourceTextureViewComponent->GetSprite()->ConvertWorldSpaceToTextureSpace(WorldPoint);
	//		for (int32 RelatedSpriteIndex = 0; RelatedSpriteIndex < RelatedSprites.Num(); ++RelatedSpriteIndex)
	//		{
	//			FRelatedSprite& RelatedSprite = RelatedSprites[RelatedSpriteIndex];
	//			if ((TexturePoint.X >= RelatedSprite.SourceUV.X) && (TexturePoint.Y >= RelatedSprite.SourceUV.Y) &&
	//				(TexturePoint.X < (RelatedSprite.SourceUV.X + RelatedSprite.SourceDimension.X)) &&
	//				(TexturePoint.Y < (RelatedSprite.SourceUV.Y + RelatedSprite.SourceDimension.Y)))
	//			{
	//				bHandled = true;
	//
	//				// Select this sprite
	//				if (UPaperSprite* LoadedSprite = Cast<UPaperSprite>(RelatedSprite.AssetData.GetAsset()))
	//				{
	//					if (SpriteEditorPtr.IsValid())
	//					{
	//						SpriteEditorPtr.Pin()->SetSpriteBeingEdited(LoadedSprite);
	//						break;
	//					}
	//				}
	//			}
	//		}
	//	}
	//}

	if (!bHandled)
	{
		FVoreealEditorViewportClient::ProcessClick(View, HitProxy, Key, Event, HitX, HitY);
	}
}

bool FBasicVolumeEditorViewportClient::InputKey(FViewport* pViewport, int32 ControllerId, FKey Key, EInputEvent Event, float AmountDepressed, bool bGamepad)
{
	bool bHandled = false;
	FInputEventState InputState(pViewport, Key, Event);

	// Pass keys to standard controls, if we didn't consume input
	return (bHandled) ? true : FEditorViewportClient::InputKey(pViewport, ControllerId, Key, Event, AmountDepressed, bGamepad);
}

void FBasicVolumeEditorViewportClient::TrackingStarted(const struct FInputEventState& InInputState, bool bIsDragging, bool bNudge)
{
	// Begin transacting.  Give the current editor mode an opportunity to do the transacting.
	const bool bTrackingHandledExternally = ModeTools->StartTracking(this, Viewport);

	if (!bManipulating && bIsDragging && !bTrackingHandledExternally)
	{
		bManipulating = true;
		bManipulationDirtiedSomething = false;
	}
}

void FBasicVolumeEditorViewportClient::TrackingStopped()
{
	// Stop transacting.  Give the current editor mode an opportunity to do the transacting.
	const bool bTransactingHandledByEditorMode = ModeTools->EndTracking(this, Viewport);

	if (bManipulating && !bTransactingHandledByEditorMode)
	{
		bManipulating = false;
	}
}

FLinearColor FBasicVolumeEditorViewportClient::GetBackgroundColor() const
{
	return FLinearColor::Black;
}

void FBasicVolumeEditorViewportClient::NotifyVolumeBeingEditedHasChanged()
{
	// Refresh the viewport in case we were not in realtime mode
	Invalidate();

	// Update components to know about the new volume being edited
	UBasicVolume* Volume = GetVolumeBeingEdited();

	RenderVolumeComponent->SetBasicVolume(Volume);

	InternalActivateNewMode(CurrentMode);

	if (Volume != nullptr)
	{
		// Create and display a notification about the new volume being edited
		const FText NotificationErrorText = FText::Format(LOCTEXT("SwitchingToVolume", "Editing {0}"), FText::AsCultureInvariant(Volume->GetName()));
		FNotificationInfo Info(NotificationErrorText);
		Info.ExpireDuration = 2.0f;
		FSlateNotificationManager::Get().AddNotification(Info);
	}
}

void FBasicVolumeEditorViewportClient::InternalActivateNewMode(EBasicVolumeEditorMode NewMode)
{
	CurrentMode = NewMode;
	Viewport->InvalidateHitProxy();

	UBasicVolume* Volume = GetVolumeBeingEdited();

	switch (CurrentMode)
	{
	case EBasicVolumeEditorMode::ViewMode:
		break;
	case EBasicVolumeEditorMode::EditMode:
		break;
	}
}

#undef LOCTEXT_NAMESPACE
<commit_msg>clean up<commit_after>#include "VoreealEditorPrivatePCH.h"
#include "BasicVolumeEditorViewportClient.h"

#include "SceneViewport.h"
#include "PreviewScene.h"
#include "ScopedTransaction.h"
#include "Runtime/Engine/Public/ComponentReregisterContext.h"

#include "AssetToolsModule.h"
#include "ContentBrowserModule.h"
#include "AssetRegistryModule.h"
#include "CanvasTypes.h"
#include "CanvasItem.h"

#include "SEditorViewport.h"
#include "SNotificationList.h"
#include "NotificationManager.h"

#include "BasicVolumeEditorSettings.h"

#define LOCTEXT_NAMESPACE "VoreealEditor"

FBasicVolumeEditorViewportClient::FBasicVolumeEditorViewportClient(TWeakPtr<FBasicVolumeEditor> InEditor, TWeakPtr<class SEditorViewport> InEditorViewportPtr)
	: CurrentMode(EBasicVolumeEditorMode::ViewMode)
	, EditorPtr(InEditor)
	, EditorViewportPtr(InEditorViewportPtr)
{
	check(EditorPtr.IsValid() && EditorViewportPtr.IsValid());

	Widget->SetUsesEditorModeTools(ModeTools);

	PreviewScene = &OwnedPreviewScene;
	((FAssetEditorModeManager*)ModeTools)->SetPreviewScene(PreviewScene);

	SetRealtime(true);

	bManipulating = false;
	bManipulationDirtiedSomething = false;
	ScopedTransaction = nullptr;

	bShowOctree = true;
	bShowSockets = true;
	bShowPivot = true;

	DrawHelper.bDrawGrid = GetDefault<UBasicVolumeEditorSettings>()->bShowGridByDefault;

	EngineShowFlags.DisableAdvancedFeatures();
	EngineShowFlags.SetCompositeEditorPrimitives(true);

	// Create a render component for the volume being edited
	{
		RenderVolumeComponent = NewObject<UBasicVolumeComponent>();
		UBasicVolume* Volume = GetVolumeBeingEdited();
		RenderVolumeComponent->SetBasicVolume(Volume);

		PreviewScene->AddComponent(RenderVolumeComponent, FTransform::Identity);
	}
}

void FBasicVolumeEditorViewportClient::ActivateEditMode()
{
	ModeTools->SetWidgetMode(FWidget::WM_Translate);
}

#pragma region // Begin Show Flags
void FBasicVolumeEditorViewportClient::SetShowOctree(bool bShow)
{
	bShowOctree = !bShowOctree;
	Invalidate();
}

void FBasicVolumeEditorViewportClient::ToggleShowOctree()
{
	bShowOctree = !bShowOctree;
	Invalidate();
}

bool FBasicVolumeEditorViewportClient::IsSetShowOctreeChecked() const
{
	return bShowOctree;
}

void FBasicVolumeEditorViewportClient::ToggleShowSockets()
{
	bShowSockets = !bShowSockets;
	Invalidate();
}

bool FBasicVolumeEditorViewportClient::IsShowSocketsChecked() const
{
	return bShowSockets;
}

void FBasicVolumeEditorViewportClient::ToggleShowPivot()
{
	bShowPivot = !bShowPivot;
	Invalidate();
}

bool FBasicVolumeEditorViewportClient::IsShowPivotChecked() const
{
	return bShowPivot;
}
#pragma endregion

void FBasicVolumeEditorViewportClient::EnterViewMode()
{
	InternalActivateNewMode(EBasicVolumeEditorMode::ViewMode);
}

void FBasicVolumeEditorViewportClient::EnterEditMode()
{
	InternalActivateNewMode(EBasicVolumeEditorMode::EditMode);
}

bool FBasicVolumeEditorViewportClient::IsInViewMode() const
{
	return CurrentMode == EBasicVolumeEditorMode::ViewMode;
}

bool FBasicVolumeEditorViewportClient::IsInEditMode() const
{
	return CurrentMode == EBasicVolumeEditorMode::EditMode;
}

void FBasicVolumeEditorViewportClient::DrawCanvas(FViewport& pViewport, FSceneView& View, FCanvas& Canvas)
{
	const bool bIsHitTesting = Canvas.IsHitTesting();
	if (!bIsHitTesting)
	{
		Canvas.SetHitProxy(nullptr);
	}

	if (!EditorPtr.IsValid())
	{
		return;
	}

	UBasicVolume* Volume = GetVolumeBeingEdited();

	switch (CurrentMode)
	{
	default:
	case EBasicVolumeEditorMode::ViewMode:
		break;
	case EBasicVolumeEditorMode::EditMode:
		break;
	}

	if (bShowSockets && !IsInEditMode())
	{
		//FSpriteGeometryEditMode* GeometryEditMode = ModeTools->GetActiveModeTyped<FSpriteGeometryEditMode>(FSpriteGeometryEditMode::EM_SpriteGeometry);
		//FSocketEditingHelper::DrawSocketNames(GeometryEditMode, RenderVolumeComponent, Viewport, View, Canvas);
	}

	FEditorViewportClient::DrawCanvas(pViewport, View, Canvas);
}

void FBasicVolumeEditorViewportClient::Draw(const FSceneView* View, FPrimitiveDrawInterface* PDI)
{
	FEditorViewportClient::Draw(View, PDI);

	if (IsInEditMode())
	{
		if (bShowPivot)
		{
			const bool bCanSelectPivot = false;
			const bool bHitTestingForPivot = PDI->IsHitTesting() && bCanSelectPivot;
			FUnrealEdUtils::DrawWidget(View, PDI, RenderVolumeComponent->ComponentToWorld.ToMatrixWithScale(), 0, 0, EAxisList::XZ, EWidgetMovementMode::WMM_Translate, bHitTestingForPivot);
		}

		if (bShowSockets)
		{
			//FSpriteGeometryEditMode* GeometryEditMode = ModeTools->GetActiveModeTyped<FSpriteGeometryEditMode>(FSpriteGeometryEditMode::EM_SpriteGeometry);
			//FSocketEditingHelper::DrawSockets(GeometryEditMode, RenderSpriteComponent, View, PDI);
		}
	}
}

FBox FBasicVolumeEditorViewportClient::GetDesiredFocusBounds() const
{
	UBasicVolumeComponent* ComponentToFocusOn = RenderVolumeComponent;
	return ComponentToFocusOn->Bounds.GetBox();
}

void FBasicVolumeEditorViewportClient::Tick(float DeltaSeconds)
{
	if (UBasicVolume* Volume = GetVolumeBeingEdited())
	{

	}

	FVoreealEditorViewportClient::Tick(DeltaSeconds);

	// Draw the octree
	if (bShowOctree && RenderVolumeComponent)
	{
		RenderVolumeComponent->DrawDebugOctree(FLinearColor::Red, 0, 1.0f);
	}

	if (!GIntraFrameDebuggingGameThread)
	{
		OwnedPreviewScene.GetWorld()->Tick(LEVELTICK_All, DeltaSeconds);
	}
}

void FBasicVolumeEditorViewportClient::ProcessClick(FSceneView& View, HHitProxy* HitProxy, FKey Key, EInputEvent Event, uint32 HitX, uint32 HitY)
{
	const FViewportClick Click(&View, this, Key, Event, HitX, HitY);
	const bool bIsCtrlKeyDown = Viewport->KeyState(EKeys::LeftControl) || Viewport->KeyState(EKeys::RightControl);
	const bool bIsShiftKeyDown = Viewport->KeyState(EKeys::LeftShift) || Viewport->KeyState(EKeys::RightShift);
	const bool bIsAltKeyDown = Viewport->KeyState(EKeys::LeftAlt) || Viewport->KeyState(EKeys::RightAlt);

	bool bHandled = false;
	if (!bHandled)
	{
		FVoreealEditorViewportClient::ProcessClick(View, HitProxy, Key, Event, HitX, HitY);
	}
}

bool FBasicVolumeEditorViewportClient::InputKey(FViewport* pViewport, int32 ControllerId, FKey Key, EInputEvent Event, float AmountDepressed, bool bGamepad)
{
	bool bHandled = false;
	FInputEventState InputState(pViewport, Key, Event);

	// Pass keys to standard controls, if we didn't consume input
	return (bHandled) ? true : FEditorViewportClient::InputKey(pViewport, ControllerId, Key, Event, AmountDepressed, bGamepad);
}

void FBasicVolumeEditorViewportClient::TrackingStarted(const struct FInputEventState& InInputState, bool bIsDragging, bool bNudge)
{
	// Begin transacting.  Give the current editor mode an opportunity to do the transacting.
	const bool bTrackingHandledExternally = ModeTools->StartTracking(this, Viewport);

	if (!bManipulating && bIsDragging && !bTrackingHandledExternally)
	{
		bManipulating = true;
		bManipulationDirtiedSomething = false;
	}
}

void FBasicVolumeEditorViewportClient::TrackingStopped()
{
	// Stop transacting.  Give the current editor mode an opportunity to do the transacting.
	const bool bTransactingHandledByEditorMode = ModeTools->EndTracking(this, Viewport);

	if (bManipulating && !bTransactingHandledByEditorMode)
	{
		bManipulating = false;
	}
}

FLinearColor FBasicVolumeEditorViewportClient::GetBackgroundColor() const
{
	return FLinearColor::Black;
}

void FBasicVolumeEditorViewportClient::NotifyVolumeBeingEditedHasChanged()
{
	// Refresh the viewport in case we were not in realtime mode
	Invalidate();

	// Update components to know about the new volume being edited
	UBasicVolume* Volume = GetVolumeBeingEdited();

	RenderVolumeComponent->SetBasicVolume(Volume);

	InternalActivateNewMode(CurrentMode);

	if (Volume != nullptr)
	{
		// Create and display a notification about the new volume being edited
		const FText NotificationErrorText = FText::Format(LOCTEXT("SwitchingToVolume", "Editing {0}"), FText::AsCultureInvariant(Volume->GetName()));
		FNotificationInfo Info(NotificationErrorText);
		Info.ExpireDuration = 2.0f;
		FSlateNotificationManager::Get().AddNotification(Info);
	}
}

void FBasicVolumeEditorViewportClient::InternalActivateNewMode(EBasicVolumeEditorMode NewMode)
{
	CurrentMode = NewMode;
	Viewport->InvalidateHitProxy();

	UBasicVolume* Volume = GetVolumeBeingEdited();

	switch (CurrentMode)
	{
	case EBasicVolumeEditorMode::ViewMode:
		break;
	case EBasicVolumeEditorMode::EditMode:
		break;
	}
}

#undef LOCTEXT_NAMESPACE
<|endoftext|>


<commit_before>#include <CGAL/Exact_predicates_inexact_constructions_kernel.h>
#include <CGAL/boost/graph/graph_traits_Polyhedron_3.h>
#include <CGAL/Polyhedron_items_with_id_3.h>
#include <CGAL/IO/Polyhedron_iostream.h>
#include <CGAL/mesh_segmentation.h>
#include <CGAL/property_map.h>
#include <iostream>
#include <fstream>
#include <string>

typedef CGAL::Exact_predicates_inexact_constructions_kernel K;
typedef CGAL::Polyhedron_3<K, CGAL::Polyhedron_items_with_id_3>  Polyhedron;

// Property map associating a facet with an integer as id to an
// element in a vector stored internally
template<class ValueType>
struct Facet_with_id_pmap
    : public boost::put_get_helper<ValueType&,
             Facet_with_id_pmap<ValueType> >
{
    typedef Polyhedron::Facet_const_handle key_type;
    typedef ValueType value_type;
    typedef value_type& reference;
    typedef boost::lvalue_property_map_tag category;

    Facet_with_id_pmap(
      std::vector<ValueType>& internal_vector
    ) : internal_vector(internal_vector) { }
    reference operator[](key_type key) const
    { return internal_vector[key->id()]; }
private:
    std::vector<ValueType>& internal_vector;
};

int main(int argc,char* argv[])
{
	typedef Polyhedron::Facet_iterator                   Facet_iterator;
    typedef Polyhedron::Halfedge_around_facet_circulator Halfedge_facet_circulator;

std::string location;
std::string filePath;
    // create and read Polyhedron
    if (argc==1){
		// TODO: Petteri, maybe change the paths when providing no arguments to something else
    	location= "/home/highschoolintern/Desktop/TestReconstruction2/testReconstruction_4slicesPhysical_reconstruction_isolatedRemoved_decimated.off";
    	filePath= "/home/highschoolintern/Desktop/SDFPropertyMap/build";

    }else {
    	location= argv[1];
    	filePath= argv[2];
    }

   std::cout << location.c_str() << "\n";

   Polyhedron mesh;
    std::ifstream input(location.c_str());
    if ( !input || !(input >> mesh) || mesh.empty() ) {
      std::cerr << "Not a valid off file." << std::endl;

      return EXIT_FAILURE;
    }

    // assign id field for each facet
    std::size_t facet_id = 0;
    for(Polyhedron::Facet_iterator facet_it = mesh.facets_begin();
      facet_it != mesh.facets_end(); ++facet_it, ++facet_id) {
        facet_it->id() = facet_id;

    }

    for (  Facet_iterator i = mesh.facets_begin(); i != mesh.facets_end(); ++i) {
        Halfedge_facet_circulator j = i->facet_begin();
        // Facets in polyhedral surfaces are at least triangles.
        CGAL_assertion( CGAL::circulator_size(j) >= 3);
        //std::cout << CGAL::circulator_size(j) << ' ';
        do {
           // std::cout << ' ' << std::distance(mesh.vertices_begin(), j->vertex());

        } while ( ++j != i->facet_begin());
        //std::cout << std::endl;
    }

// create a property-map for SDF values
    std::vector<double> sdf_values(mesh.size_of_facets());
    Facet_with_id_pmap<double> sdf_property_map(sdf_values);
    CGAL::sdf_values(mesh, sdf_property_map);

// access SDF values (with constant-complexity)
std::ofstream SDF(filePath.c_str());
SDF.open("SDFVals.txt");

    for(Polyhedron::Facet_const_iterator facet_it = mesh.facets_begin();
      facet_it != mesh.facets_end(); ++facet_it) {
        std::cout << sdf_property_map[facet_it] << " \n";
   SDF << sdf_property_map[facet_it] << std::endl;
    }
    SDF.close();
    std::cout << std::endl;

    std::ofstream SDFfile;

    // create a property-map for segment-ids
    std::vector<std::size_t> segment_ids(mesh.size_of_facets());
    Facet_with_id_pmap<std::size_t> segment_property_map(segment_ids);
    CGAL::segmentation_from_sdf_values(mesh, sdf_property_map, segment_property_map);

    // access segment-ids (with constant-complexity)
    for(Polyhedron::Facet_const_iterator facet_it = mesh.facets_begin();
      facet_it != mesh.facets_end(); ++facet_it) {
        std::cout << segment_property_map[facet_it] << " ";
    }
    std::cout << std::endl;

    SDFfile.close();

}

<commit_msg>some comments added<commit_after>#include <CGAL/Exact_predicates_inexact_constructions_kernel.h>
#include <CGAL/boost/graph/graph_traits_Polyhedron_3.h>
#include <CGAL/Polyhedron_items_with_id_3.h>
#include <CGAL/IO/Polyhedron_iostream.h>
#include <CGAL/mesh_segmentation.h>
#include <CGAL/property_map.h>
#include <iostream>
#include <fstream>
#include <string>

typedef CGAL::Exact_predicates_inexact_constructions_kernel K;
typedef CGAL::Polyhedron_3<K, CGAL::Polyhedron_items_with_id_3>  Polyhedron;

// Property map associating a facet with an integer as id to an
// element in a vector stored internally
template<class ValueType>
struct Facet_with_id_pmap
    : public boost::put_get_helper<ValueType&,
             Facet_with_id_pmap<ValueType> >
{
    typedef Polyhedron::Facet_const_handle key_type;
    typedef ValueType value_type;
    typedef value_type& reference;
    typedef boost::lvalue_property_map_tag category;

    Facet_with_id_pmap(
      std::vector<ValueType>& internal_vector
    ) : internal_vector(internal_vector) { }
    reference operator[](key_type key) const
    { return internal_vector[key->id()]; }
private:
    std::vector<ValueType>& internal_vector;
};

int main(int argc,char* argv[])
{
	typedef Polyhedron::Facet_iterator                   Facet_iterator;
    typedef Polyhedron::Halfedge_around_facet_circulator Halfedge_facet_circulator;

std::string location;
std::string filePath;
    // create and read Polyhedron
    if (argc==1){
		// TODO: Petteri, maybe change the paths when providing no arguments to something else
    	location= "/home/highschoolintern/Desktop/TestReconstruction2/testReconstruction_4slicesPhysical_reconstruction_isolatedRemoved_decimated.off";
    	filePath= "/home/highschoolintern/Desktop/SDFPropertyMap/build";

    }else {
    	location= argv[1];
    	filePath= argv[2];
    }

   std::cout << location.c_str() << "\n";

   Polyhedron mesh;
    std::ifstream input(location.c_str());
    if ( !input || !(input >> mesh) || mesh.empty() ) {
      std::cerr << "Not a valid off file." << std::endl;

      return EXIT_FAILURE;
    }

    // assign id field for each facet
    std::size_t facet_id = 0;
    for(Polyhedron::Facet_iterator facet_it = mesh.facets_begin();
      facet_it != mesh.facets_end(); ++facet_it, ++facet_id) {
        facet_it->id() = facet_id;

    }

    for (  Facet_iterator i = mesh.facets_begin(); i != mesh.facets_end(); ++i) {
        Halfedge_facet_circulator j = i->facet_begin();
        // Facets in polyhedral surfaces are at least triangles.
        CGAL_assertion( CGAL::circulator_size(j) >= 3);
        //std::cout << CGAL::circulator_size(j) << ' ';
        do {
           // std::cout << ' ' << std::distance(mesh.vertices_begin(), j->vertex());

        } while ( ++j != i->facet_begin());
        //std::cout << std::endl;
    }

// create a property-map for SDF values
    std::vector<double> sdf_values(mesh.size_of_facets());
    Facet_with_id_pmap<double> sdf_property_map(sdf_values);
    CGAL::sdf_values(mesh, sdf_property_map);

// access SDF values (with constant-complexity)
std::ofstream SDF(filePath.c_str());
SDF.open("SDFVals.txt");

    for(Polyhedron::Facet_const_iterator facet_it = mesh.facets_begin();
      facet_it != mesh.facets_end(); ++facet_it) {
        std::cout << sdf_property_map[facet_it] << " \n";
   SDF << sdf_property_map[facet_it] << std::endl;
    }
    SDF.close();
    std::cout << std::endl; // Printing the SDF values

    std::ofstream SDFfile;

    // create a property-map for segment-ids
    std::vector<std::size_t> segment_ids(mesh.size_of_facets());
    Facet_with_id_pmap<std::size_t> segment_property_map(segment_ids);
    CGAL::segmentation_from_sdf_values(mesh, sdf_property_map, segment_property_map);

    // access segment-ids (with constant-complexity)
    for(Polyhedron::Facet_const_iterator facet_it = mesh.facets_begin();
      facet_it != mesh.facets_end(); ++facet_it) {
        std::cout << segment_property_map[facet_it] << " ";
    }
    std::cout << std::endl; // Printing the SDF Segment IDs

        // These IDs could be saved to disk maybe as well, and used in piecewise denoising or something?

    SDFfile.close();

}

<|endoftext|>


<commit_before>// This file is a part of the IncludeOS unikernel - www.includeos.org
//
// Copyright 2015-2016 Oslo and Akershus University College of Applied Sciences
// and Alfred Bratterud
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

#ifndef HTTP_METHODS_HPP
#define HTTP_METHODS_HPP

#include <array>
#include <string>
#include <ostream>

namespace http {

  enum Method {
    GET, POST, PUT, DELETE, OPTIONS, HEAD, TRACE, CONNECT, PATCH,
    INVALID = 0xffff
  };

  namespace method {

    /** Get method string from method code **/
    inline const std::string& str(const Method m) {

      static std::array<std::string, 10> strings
      {
        {
         "GET", "POST", "PUT", "DELETE", "OPTIONS",
         "HEAD", "TRACE", "CONNECT", "PATCH", "INVALID"
        }
      };

      if ((m >= 0) and (m < (strings.size() - 1))) {
        return strings[m];
      }

      return strings[strings.size() - 1];
    }

    /**
     * Get a code mapping from an HTTP
     * method
     *
     * @param method - The HTTP method
     *
     * @return - The code mapped to the method
     **/
    inline Method code(const std::string& method) noexcept {

      if (method == str(GET))     return GET;
      if (method == str(POST))    return POST;
      if (method == str(PUT))     return PUT;
      if (method == str(DELETE))  return DELETE;
      if (method == str(OPTIONS)) return OPTIONS;
      if (method == str(HEAD))    return HEAD;
      if (method == str(TRACE))   return TRACE;
      if (method == str(CONNECT)) return CONNECT;
      if (method == str(PATCH))   return PATCH;

      return INVALID;
    }

  } // namespace method

  std::ostream& operator << (std::ostream& output_device, const Method m) {
    return output_device << http::method::str(m);
  }

} // namespace http

#endif // HTTP_METHODS_HPP
<commit_msg>Inlined function since it resides in a header...<commit_after>// This file is a part of the IncludeOS unikernel - www.includeos.org
//
// Copyright 2015-2016 Oslo and Akershus University College of Applied Sciences
// and Alfred Bratterud
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

#ifndef HTTP_METHODS_HPP
#define HTTP_METHODS_HPP

#include <array>
#include <string>
#include <ostream>

namespace http {

  enum Method {
    GET, POST, PUT, DELETE, OPTIONS, HEAD, TRACE, CONNECT, PATCH,
    INVALID = 0xffff
  };

  namespace method {

    /** Get method string from method code **/
    inline const std::string& str(const Method m) {

      static std::array<std::string, 10> strings
      {
        {
         "GET", "POST", "PUT", "DELETE", "OPTIONS",
         "HEAD", "TRACE", "CONNECT", "PATCH", "INVALID"
        }
      };

      if ((m >= 0) and (m < (strings.size() - 1))) {
        return strings[m];
      }

      return strings[strings.size() - 1];
    }

    /**
     * Get a code mapping from an HTTP
     * method
     *
     * @param method - The HTTP method
     *
     * @return - The code mapped to the method
     **/
    inline Method code(const std::string& method) noexcept {

      if (method == str(GET))     return GET;
      if (method == str(POST))    return POST;
      if (method == str(PUT))     return PUT;
      if (method == str(DELETE))  return DELETE;
      if (method == str(OPTIONS)) return OPTIONS;
      if (method == str(HEAD))    return HEAD;
      if (method == str(TRACE))   return TRACE;
      if (method == str(CONNECT)) return CONNECT;
      if (method == str(PATCH))   return PATCH;

      return INVALID;
    }

  } // namespace method

  inline std::ostream& operator << (std::ostream& output_device, const Method m) {
    return output_device << http::method::str(m);
  }

} // namespace http

#endif // HTTP_METHODS_HPP
<|endoftext|>


<commit_before>#include "text.h"
#include <vector>
#include <memory>

using std::move;
using std::vector;
using std::unique_ptr;
using std::ostream;

TextSlice::TextSlice(Text &text) : text{&text}, start_index{0}, end_index{text.size()} {}

TextSlice::TextSlice(Text *text, size_t start_index, size_t end_index)
    : text{text}, start_index{start_index}, end_index{end_index} {}

Text::iterator TextSlice::begin() {
  return text->begin() + start_index;
}

size_t TextSlice::size() {
  return end_index - start_index;
}

Text::iterator TextSlice::end() {
  return text->begin() + end_index;
}

Text TextSlice::Concat(TextSlice a, TextSlice b) {
  Text result;
  result.reserve(a.size() + b.size());
  result.insert(
    result.end(),
    a.begin(),
    a.end()
  );
  result.insert(
    result.end(),
    b.begin(),
    b.end()
  );
  return result;
}

Text TextSlice::Concat(TextSlice a, TextSlice b, TextSlice c) {
  Text result;
  result.reserve(a.size() + b.size() + c.size());
  result.insert(
    result.end(),
    a.begin(),
    a.end()
  );
  result.insert(
    result.end(),
    b.begin(),
    b.end()
  );
  result.insert(
    result.end(),
    c.begin(),
    c.end()
  );
  return result;
}

TextSlice::operator Text() const {
  return Text(text->begin() + start_index, text->begin() + end_index);
}

std::pair<TextSlice, TextSlice> TextSlice::Split(Point position) {
  size_t index = CharacterIndexForPosition(position);
  return {
    TextSlice{text, start_index, start_index + index},
    TextSlice{text, start_index + index, end_index}
  };
}

TextSlice TextSlice::Suffix(Point suffix_start) {
  return Split(suffix_start).second;
}

TextSlice TextSlice::Prefix(Point prefix_end) {
  return Split(prefix_end).first;
}

size_t TextSlice::CharacterIndexForPosition(Point target) {
  Point position;
  auto begin = text->begin() + start_index;
  auto end = text->begin() + end_index;
  auto iter = begin;
  while (iter != end && position < target) {
    if (*iter == '\n') {
      position.row++;
      position.column = 0;
    } else {
      position.column++;
    }
    ++iter;
  }

  return iter - begin;
}

ostream &operator<<(ostream &stream, const Text *text) {
  if (text) {
    stream << "'";
    for (uint16_t character : *text) {
      if (character < CHAR_MAX) {
        stream << (char)character;
      } else {
        stream << "\\u" << character;
      }
    }
    stream << "'";
    return stream;
  } else {
    return stream << "null";
  }
}
<commit_msg>Include limits.h for CHAR_MAX<commit_after>#include "text.h"
#include <limits.h>
#include <vector>
#include <memory>

using std::move;
using std::vector;
using std::unique_ptr;
using std::ostream;

TextSlice::TextSlice(Text &text) : text{&text}, start_index{0}, end_index{text.size()} {}

TextSlice::TextSlice(Text *text, size_t start_index, size_t end_index)
    : text{text}, start_index{start_index}, end_index{end_index} {}

Text::iterator TextSlice::begin() {
  return text->begin() + start_index;
}

size_t TextSlice::size() {
  return end_index - start_index;
}

Text::iterator TextSlice::end() {
  return text->begin() + end_index;
}

Text TextSlice::Concat(TextSlice a, TextSlice b) {
  Text result;
  result.reserve(a.size() + b.size());
  result.insert(
    result.end(),
    a.begin(),
    a.end()
  );
  result.insert(
    result.end(),
    b.begin(),
    b.end()
  );
  return result;
}

Text TextSlice::Concat(TextSlice a, TextSlice b, TextSlice c) {
  Text result;
  result.reserve(a.size() + b.size() + c.size());
  result.insert(
    result.end(),
    a.begin(),
    a.end()
  );
  result.insert(
    result.end(),
    b.begin(),
    b.end()
  );
  result.insert(
    result.end(),
    c.begin(),
    c.end()
  );
  return result;
}

TextSlice::operator Text() const {
  return Text(text->begin() + start_index, text->begin() + end_index);
}

std::pair<TextSlice, TextSlice> TextSlice::Split(Point position) {
  size_t index = CharacterIndexForPosition(position);
  return {
    TextSlice{text, start_index, start_index + index},
    TextSlice{text, start_index + index, end_index}
  };
}

TextSlice TextSlice::Suffix(Point suffix_start) {
  return Split(suffix_start).second;
}

TextSlice TextSlice::Prefix(Point prefix_end) {
  return Split(prefix_end).first;
}

size_t TextSlice::CharacterIndexForPosition(Point target) {
  Point position;
  auto begin = text->begin() + start_index;
  auto end = text->begin() + end_index;
  auto iter = begin;
  while (iter != end && position < target) {
    if (*iter == '\n') {
      position.row++;
      position.column = 0;
    } else {
      position.column++;
    }
    ++iter;
  }

  return iter - begin;
}

ostream &operator<<(ostream &stream, const Text *text) {
  if (text) {
    stream << "'";
    for (uint16_t character : *text) {
      if (character < CHAR_MAX) {
        stream << (char)character;
      } else {
        stream << "\\u" << character;
      }
    }
    stream << "'";
    return stream;
  } else {
    return stream << "null";
  }
}
<|endoftext|>


<commit_before>/** \mainpage

# Contents
- Overview
- Requirements
- Building
- Design and Rationale
- Examples

# Overview

This library consists of a set of templated functions for doing basic arithmetic
operations on ranges and containers. It assumes that the elements of the
ranges/containers support the arithmetic operators: +, -, *, /.

From a mathematical point of view it works on vector spaces in arbitrary dimensions.
It does not define any specific data structure for the vectors.
Instead it provides functions that implement vector space operations
for arbitrary ranges/containers.

The library consists of the modules:
- **Vector space operations**. This module defines the algorithms:
    - **add**. Does elementwise addition of either two ranges/containers,
      or a scalar and a range/container.
    - **subtract**. Does elementwise subtraction of either two ranges/containers,
      or a scalar and a range/container.
    - **negate**. Does elementwise negation of a range/container.
    - **multiply**. Does elementwise multiplication of either two ranges/containers,
      or a scalar and a range/container.
    - **divide**. Does elementwise division of either two ranges/containers,
      or a scalar and a range/container.
- **Euclidean space operations**. This module defines the algorithms:
    - **norm**. Computes the Euclidean norm of a range/container.
    - **squared_norm**. Computes the squared Euclidean norm of a range/container.
    - **dot**. Computes the Euclidean inner product of two ranges/containers.
    - **distance**. Computes the Euclidean distance of two ranges/containers.
    - **squared_distance**. Computes the squared Euclidean distance of two
      ranges/containers.
- **Taxicab space operations**. This module defines the algorithms:
    - **norm_l1**. Computes the Taxicab/Manhattan/L1 norm of a range/container.
    - **squared_norm_l1**. Computes the squared Taxicab/Manhattan/L1 norm of a range/container.
    - **distance_l1**. Computes the Taxicab/Manhattan/L1 distance of two ranges/containers.
    - **squared_distance_l1**. Computes the squared Taxicab/Manhattan/L1 distance of two
      ranges/containers.
- **Chebyshev space operations**. This module defines the algorithms:
    - **norm_max**. Computes the Chebyshev/Infinity/Max norm of a range/container.
    - **squared_norm_max**. Computes the squared Chebyshev/Infinity/Max norm of a range/container.
    - **distance_max**. Computes the Chebyshev/Infinity/Max distance of two ranges/containers.
    - **squared_distance_max**. Computes the squared Chebyshev/Infinity/Max distance of two
      ranges/containers.
- **Misc algorithms**. This module defines the aglorithms:
    - **sum**. Computes the sum of the elements of a range/container.
    - **convert**. Does elementwise `static_cast` on the elements from one
      range/container to another range/container.
- **STD algorithms**. This module defines container versions of some range
  algorithms from the standard library header `<algorithm>`. It only does it for
  the algorithms that are used a lot for arithmetic types:
    - **copy**.
    - **fill**.
    - **min_element**.
    - **max_element**.
    - **minmax_element**.
- **Logical operations**. This module works on Ranges/Containers with elements
  of type `bool`. The module defines the algorithms:
    - **logical_and**. Does elementwise boolean `and` on two ranges/containers.
    - **logical_or**. Does elementwise boolean `or` on two ranges/containers.
    - **logical_not**. Does elementwise boolean `not` on a range/container.

Go to the **Modules** pages to learn more about each module.

# Requirements

All the functions of this library assume that the input and output is:
- Either ranges of iterators, or standard like containers, i.e. they have begin
  and end functions that give iterators.
- The elements of the ranges/containers should support arithmetic operations:
  +, -, *, /. The functions in the module *Logical Operations* is the only
  exception to this. It assumes that the elements have type `bool`.

# Building

The library is header only, which makes it easy to use and build. Download it
and add it to the include directory of your project and `#include <aaa.hpp>`.

# Design and Rationale

This library deals with arithmetic operations on mathematical vectors,
represented as ranges or containers.
It is designed for vectors in arbitrary dimensions. It is NOT optimized for small
vectors, which you typically use to represent geometry in 2D and 3D. For that
use case it might be more optimal to use other libraries like:
[GLM](http://glm.g-truc.net/) and [Eigen](http://eigen.tuxfamily.org/).

C++ libraries that deals with mathematical vectors in arbitrary dimensions
can usually be divided into two categories:
-# Those that implement a vector class and overload its arithmetic operators.
   Examples of this are:
   [std::valarray](http://www.cplusplus.com/reference/valarray/),
   [Eigen](http://eigen.tuxfamily.org/),
   [Blitz++](https://sourceforge.net/projects/blitz/),
   [OpenCV](http://opencv.org/).
-# Those that implement general algorithms that work on any container or
   range of iterators. An example of this is the standard library and the headers
   [algorithm](http://www.cplusplus.com/reference/algorithm/)
   and [numeric](http://www.cplusplus.com/reference/numeric/).

This library follows the second approach. It implements some common arithmetic
algorithms that are missing in the standard library.

The two approaches have different advantages and disadvantages:
-# The advantage of the first approach is that the syntax can be very concise,
   when you overload the arithmetic operators to act directly on the vector class.
   This approach can also have performance advantages, since it couples the
   algorithm to the data structure. It is then possible to use techniques
   like *expression templates* or *aligned memory* and *vectorization*.
-# The advantage of the second approach is that it allows *generic programming*.
   Code that uses such libraries is more general since it is less coupled to a
   specific data structure. This is good for readability and reuse of the code.

# Examples

The algorithms can be used on arbitrary containers like this:
```
// Blend two images.
void blend(const Image& in1, const Image& in2, Image& out)
{
    using namespace aaa;
    add(in1, in2, out); // Add the images together elementwise.
    divide(out, 2, out);// Divide the result elementwise with 2 to get the mean image.
}

// Returns the projection of a on b.
std::vector<float> project(const std::vector<float>& a, const std::vector<float>& b)
{
    using namespace aaa;
    // First we compute the scaling factor of the projection by taking the dot
    // product of the vectors. We normalize with the squared_norm of the vector
    // that we are projecting on.
    const auto scaling = dot(a, b) / squared_norm(b);
    // The projection of a on b is like b,
    // but multiplied elementwise with the scaling factor.
    auto projection = b;
    multiply(scaling, b, projection);
    return projection;
}
```
*/

// TODO: should the elements be passed by value or const reference?

#pragma once

#include "std_algorithms_container.hpp"

#include "algorithms_range.hpp"
#include "algorithms_container.hpp"

#include "vector_space_range.hpp"
#include "vector_space_container.hpp"
#include "vector_space_functional.hpp"

#include "euclidean_space_range.hpp"
#include "euclidean_space_container.hpp"

#include "taxicab_space_range.hpp"
#include "taxicab_space_container.hpp"

#include "chebyshev_space_range.hpp"
#include "chebyshev_space_container.hpp"

#include "logical_range.hpp"
#include "logical_container.hpp"
#include "logical_functional.hpp"
<commit_msg>Update documentation<commit_after>/** \mainpage

# Contents
- Overview
- Requirements
- Building
- Design and Rationale
- Examples

# Overview

This library consists of a set of templated functions for doing basic arithmetic
operations on containers and ranges of iterators. The elements of the
ranges/containers can be any built in aritmetic type, e.g.
`float`, `double`, `int`, or any other type that supports the arithmetic
operations: +, -, *, /. We refer to a range/container of arithmetic elements as
a mathematical vector. This library defines vector operations for arbitrary
finite vector spaces. This library does not define any specific data structure
for the vectors, but operates on general vectors/ranges/containers.

The library consists of different modules:
- **General operations for vector spaces**.
  This includes various versions of the functions: `add`, `subtract`, `negate`, `multiply`, `divide`.
- **Norms and metrics for vector spaces**.
  This includes various versions of the functions: `norm`, `distance`, `squared_norm`, `squared_distance`.
  The norms and distances are defined for the following vectors spaces:
  `eclidean` (L2), `tacixab` (L1), `chebyshev` (L-infinity).
- **Misc algorithms**. `sum`, `convert`.
- **Logical operations**. `logical_and`, `logical_or`, `logical_not`.
- **STD algorithms**. `fill`, `copy`, `min_element`, `max_element`, `minmax_element`.

## General Operations for Vector Spaces

This module defines elementwise arithmetic operations on vectors.
The input is two vectors/ranges/containers and the output is one vector/range/container.

- **add**. Does elementwise addition of either two vectors/ranges/containers,
    or a scalar and a vector/range/container.
- **subtract**. Does elementwise subtraction of either two vector/ranges/containers,
    or a scalar and a vector/range/container.
- **negate**. Does elementwise negation of a single vector/range/container.
- **multiply**. Does elementwise multiplication of either two vector/ranges/containers,
    or a scalar and a vector/range/container.
- **divide**. Does elementwise division of either two vectors/ranges/containers,
    or a scalar and a vector/range/container.

## Norms and Metrics for Vector Spaces

This module defines norms/lengths and metrics/distances for vectors.
These functions take one or two vectors/ranges/containers and returns a
single scalar:
 - **norm**. Computes the norm/magnitude/length of a vecor/range/container.
 - **distance**. Computes the distance of two vectors/ranges/containers.
 - **squared_norm**. Computes the squared norm of a vector/range/container.
 - **squared_distance**. Computes the squared distance of two
 vectors/ranges/containers.
 - **dot**. Computes the the dot-product of two vecors/ranges/containers.

 We consider three different kinds of vector spaces: `euclidean` (L2),
 `taxicab` (L1), `chebyshev` (L-infinity). Each kind of vector spaces has its
 own namespace, with its own versions of the functions above in it.
 However, the `dot` product is only defined for `euclidean` vector spaces.
 All the functions in this module assume that the default construction of a
 scalar gives zero, which is true for the built-in arithmetic types.

## Misc algorithms

This module defines the aglorithms:
- **sum**. Computes the sum of the elements of a range/container.
  It assume that the default construction of a scalar gives zero,
  which is true for the built-in arithmetic types.
- **convert**. Does elementwise `static_cast` on the elements from one
    range/container to another range/container.

##Logical operations

This module works on ranges/containers with elements of type `bool`,
or any other type that supports the the boolean operations &&, ||, !.
The input is one or two ranges/containers and the output is a single
range/container.
- **logical_and**. Does elementwise boolean `and` on two ranges/containers.
- **logical_or**. Does elementwise boolean `or` on two ranges/containers.
- **logical_not**. Does elementwise boolean `not` on a single range/container.

##STD algorithms

This module defines container versions of some range
algorithms from the standard library header `<algorithm>`. It only does it for
the algorithms that are used a lot for arithmetic types:
- **copy**.
- **fill**.
- **min_element**.
- **max_element**.
- **minmax_element**.

Go to the **Modules** pages to learn more about each module.

# Requirements

All the functions of this library assume that the input and output is:
- Either ranges of iterators, or standard like containers, i.e. they have begin
  and end functions that give iterators.
- The elements of the ranges/containers should support arithmetic operations:
  +, -, *, /. The functions in the module *Logical Operations* is the only
  exception to this. It assumes that the elements support the boolean operations
  &&, ||, !.
- The functions in the norms and metrics module assume that the default
  construction of a scalar gives zero, which is true for the built-in arithmetic
  types. The function `sum` also assumes this.

# Building

The library is header only, which makes it easy to use and build. Download it
and add it to the include directory of your project and `#include <aaa.hpp>`.

# Design and Rationale

This library deals with arithmetic operations on mathematical vectors,
represented as ranges or containers.
It is designed for vectors in arbitrary dimensions. It is NOT optimized for small
vectors, which you typically use to represent geometry in 2D and 3D. For that
use case it might be more optimal to use other libraries like:
[GLM](http://glm.g-truc.net/) and [Eigen](http://eigen.tuxfamily.org/).

C++ libraries that deals with mathematical vectors in arbitrary dimensions
can usually be divided into two categories:
-# Those that implement a vector class and overload its arithmetic operators.
   Examples of this are:
   [std::valarray](http://www.cplusplus.com/reference/valarray/),
   [Eigen](http://eigen.tuxfamily.org/),
   [Blitz++](https://sourceforge.net/projects/blitz/),
   [OpenCV](http://opencv.org/).
-# Those that implement general algorithms that work on any container or
   range of iterators. An example of this is the standard library and the headers
   [algorithm](http://www.cplusplus.com/reference/algorithm/)
   and [numeric](http://www.cplusplus.com/reference/numeric/).

This library follows the second approach. It implements some common arithmetic
algorithms that are missing in the standard library.

The two approaches have different advantages and disadvantages:
-# The advantage of the first approach is that the syntax can be very concise,
   when you overload the arithmetic operators to act directly on the vector class.
   This approach can also have performance advantages, since it couples the
   algorithm to the data structure. It is then possible to use techniques
   like *expression templates* or *aligned memory* and *vectorization*.
-# The advantage of the second approach is that it allows *generic programming*.
   Code that uses such libraries is more general since it is less coupled to a
   specific data structure. This is good for readability and reuse of the code.

# Examples

The algorithms can be used on arbitrary containers like this:
```
// Blend two images.
void blend(const Image& in1, const Image& in2, Image& out)
{
    using namespace aaa;
    add(in1, in2, out); // Add the images together elementwise.
    divide(out, 2, out);// Divide the result elementwise with 2 to get the mean image.
}

// Returns the projection of a on b.
std::vector<float> project(const std::vector<float>& a, const std::vector<float>& b)
{
    using namespace aaa::euclidean;
    // First we compute the scaling factor of the projection by taking the dot
    // product of the vectors. We normalize with the squared_norm of the vector
    // that we are projecting on.
    const auto scaling = dot(a, b) / squared_norm(b);
    // The projection of a on b is like b,
    // but multiplied elementwise with the scaling factor.
    auto projection = b;
    multiply(scaling, b, projection);
    return projection;
}
```
*/

// TODO: should the elements be passed by value or const reference?

#pragma once

#include "std_algorithms_container.hpp"

#include "algorithms_range.hpp"
#include "algorithms_container.hpp"

#include "vector_space_range.hpp"
#include "vector_space_container.hpp"
#include "vector_space_functional.hpp"

#include "euclidean_space_range.hpp"
#include "euclidean_space_container.hpp"

#include "taxicab_space_range.hpp"
#include "taxicab_space_container.hpp"

#include "chebyshev_space_range.hpp"
#include "chebyshev_space_container.hpp"

#include "logical_range.hpp"
#include "logical_container.hpp"
#include "logical_functional.hpp"
<|endoftext|>


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

  Program:   Monteverdi2
  Language:  C++

  Copyright (c) Centre National d'Etudes Spatiales. All rights reserved.
  See Copyright.txt for details.

  Monteverdi2 is distributed under the CeCILL licence version 2. See
  Licence_CeCILL_V2-en.txt or
  http://www.cecill.info/licences/Licence_CeCILL_V2-en.txt for more details.

  This software is distributed WITHOUT ANY WARRANTY; without even
  the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
  PURPOSE.  See the above copyright notices for more information.

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

#include "mvdDatabaseModel.h"

/*****************************************************************************/
/* INCLUDE SECTION                                                           */

//
// Qt includes (sorted by alphabetic order)
//// Must be included before system/custom includes.

//
// System includes (sorted by alphabetic order)

//
// ITK includes (sorted by alphabetic order)

//
// OTB includes (sorted by alphabetic order)

//
// Monteverdi includes (sorted by alphabetic order)
#include "mvdDatasetModel.h"
#include "mvdI18nApplication.h"

namespace mvd
{
/*
  TRANSLATOR mvd::DatabaseModel

  Necessary for lupdate to be aware of C++ namespaces.

  Context comment for translator.
*/

/*****************************************************************************/
/* CONSTANTS                                                                 */

/*****************************************************************************/
/* STATIC IMPLEMENTATION SECTION                                             */

/*****************************************************************************/
/* CLASS IMPLEMENTATION SECTION                                              */

/*******************************************************************************/
DatabaseModel
::DatabaseModel( QObject* parent ) :
  AbstractModel( parent ),
  m_DatasetModels(),
  m_SelectedDatasetModel( NULL )
{
}

/*******************************************************************************/
DatabaseModel
::~DatabaseModel()
{
}

/*******************************************************************************/
QStringList
DatabaseModel
::ListAvailableDatasets() const
{
  QDir cacheDir( I18nApplication::ConstInstance()->GetCacheDir() );

  QStringList nameFilters;
  nameFilters << QString( "*%1" ).arg( I18nApplication::DATASET_EXT );

  return cacheDir.entryList(
    nameFilters,
    QDir::Dirs | QDir::NoDotAndDotDot,
    QDir::Name
    );
}

/*******************************************************************************/
StringPairListType
DatabaseModel
::QueryDatasetModels() const
{
  StringPairListType   list;

  // need to send a list of pairs <alias, id> to know what is the
  // corresponding model to each alias in the WidgetTree
  DatasetModelMap::const_iterator it =  m_DatasetModels.begin();
  while( it != m_DatasetModels.end() )
    {
    // store alias <-> name
    StringPairType spair;
    spair.first = it.value()->GetAlias();
    spair.second = it.value()->GetName();

    // insert the pair in the list
    list.append( spair);
    ++it;
    }

  return list;
}

/*******************************************************************************/
DatasetModel*
DatabaseModel
::SelectDatasetModel( const DatasetId& id )
{
  qDebug() << this << "::SelectDatasetModel(" << id << ")";

  // Find dataset model or interrupt by exception.
  DatasetModel* datasetModel = FindDatasetModel( id );
  assert( datasetModel!=NULL );

  try
    {
    // Load dataset sub-models.
    datasetModel->LoadImageModels( -1, -1 );

    // If dataset model has been loaded, select it.
    SetSelectedDatasetModel( datasetModel );
    }
  catch( std::exception& exc )
    {
    throw exc;
    }

  // Return loaded and selected dataset model.
  return datasetModel;
}

/*******************************************************************************/
DatabaseModel::DatasetId
DatabaseModel
::RegisterDatasetModel( DatasetModel* model )
{
  assert( model!=NULL );

  // Construct DatasetId.
  DatasetId id( model->GetName() );

  // Find possible previously registerd dataset-model...
  DatasetModelMap::iterator it( m_DatasetModels.find( id ) );

  if( it!=m_DatasetModels.end() )
    {
    // BUGFIX: Clear selected dataset-model if it is to be deleted below.
    if( it.value()==m_SelectedDatasetModel )
      {
      SetSelectedDatasetModel( NULL );
      }

    // ...and destroy it.
    delete it.value();
    it.value() = NULL;
    }

  // Insert new dataset-model...
  it = m_DatasetModels.insert( id, model );

  // Re-parent dataset-model.
  model->setParent( this );

  // Signal model has changed.
  emit DatabaseChanged();

  // Return registered ID.
  return id;
}

/*******************************************************************************/
void
DatabaseModel
::ReleaseDatasetModel( const DatasetId& id )
{
  qDebug() << this << "::ReleaseDatasetModel(" << id << ")";

  // Find (key, value) pair.
  DatasetModelMap::iterator it( DatasetModelIterator( id ) );

  // release model
  delete it.value();
  it.value() = NULL;
}

/*******************************************************************************/
DatasetModel*
DatabaseModel
::NewDatasetModel( const DatasetId& id )
{
  qDebug() << this << "::NewDatasetModel(" << id << ")";

  // Find dataset model or interrupt by exception.
  DatasetModel* datasetModel = NULL;

  // Otherwise, load it from disk.
  try
    {
    // Create empty dataset model.
    datasetModel = new DatasetModel( this );

    // Build dataset model.
    assert( I18nApplication::ConstInstance() );

    DatasetModel::BuildContext context(
      I18nApplication::ConstInstance()->GetCacheDir().path(),
      id,
      id,
      false
    );

    datasetModel->BuildModel( &context );
    }

  catch( std::exception& exc )
    {
    // If loading was interrupted, delete allocated memory.
    delete datasetModel;
    datasetModel = NULL;

    // And forward interrupting exception.
    throw exc;
    }

  // Return loaded and selected dataset model.
  return datasetModel;
}

/*******************************************************************************/
void
DatabaseModel
::virtual_BuildModel( void* context )
{
  InitializeDatasetModels();
}

/*******************************************************************************/
void
DatabaseModel
::InitializeDatasetModels()
{
  QStringList datasets( ListAvailableDatasets() );

  ClearDatasetModels();

  for( QStringList::const_iterator it( datasets.begin() );
       it!=datasets.end();
       ++it )
    {
    try
      {
      DatasetModel* datasetModel = NewDatasetModel( *it );
      assert( datasetModel!=NULL );

      // by default alias == name
      m_DatasetModels.insert( datasetModel->GetName(), datasetModel );
      }
    catch( std::exception& exc )
      {
      throw exc;
      }
    }
}

/*******************************************************************************/
void
DatabaseModel
::ClearDatasetModels()
{
  while( !m_DatasetModels.empty() )
    {
    DatasetModelMap::iterator it( m_DatasetModels.begin() );

    delete it.value();
    it.value() = NULL;

    it = m_DatasetModels.erase( it );
    }
}

/*******************************************************************************/
/* SLOTS                                                                       */
/*******************************************************************************/
void
DatabaseModel
::OnDatasetToDeleteSelected( const QString&  id)
{
  // pop up a Dialog widget to confirm the user choice
  QMessageBox msgBox;
  msgBox.setWindowTitle( tr( "Warning") );
  msgBox.setText(tr("You are about to remove the dataset : \n %1 \n\n"
                    " Are your sure ? ").arg(id) );
  msgBox.setStandardButtons(QMessageBox::Yes | QMessageBox::No);
  msgBox.setDefaultButton(QMessageBox::No);
  int ret = msgBox.exec();

  // if choice confirmed
  if (ret == QMessageBox::Yes)
    {
    qDebug() << this << " ::OnDatasetToDeleteSelected -> About to remove : "<< id;

    // if current selected item is removed, make the TreeWidget
    // focusing on the root item
    if ( FindDatasetModel( id ) == GetSelectedDatasetModel() )
      {
      // set the Tree browser to point on nothing
      emit CurrentSelectedItemDeleted();

      //
      SetSelectedDatasetModel( NULL );
      }

    // get the full path to the dataset dir
    QDir datasetQDir(
      I18nApplication::Instance()->GetCacheDir().absolutePath() +
      "/" +
      id
      );
    QString datasetDir = datasetQDir.absolutePath();

    //
    // remove the files in this directory
    bool removingFilesStatus = true;
    QStringList fileList = datasetQDir.entryList( QDir::NoDotAndDotDot |  QDir::Files );
    for( int i = 0; i < fileList.count(); ++i )
      {
      qDebug()<< "Removing file "<< fileList.at(i);
      removingFilesStatus &= datasetQDir.remove( fileList.at(i) );
      }

    // go to parent dir
    QDir datasetQDirParent = datasetQDir;
    datasetQDirParent.cdUp();

    // if path removed successfuly :
    //  - release dataset model
    //  - notify change to update the database browser
    if ( removingFilesStatus &&  datasetQDirParent.rmpath( datasetDir ) )
      {
      qDebug() << this
               << " ::OnDatasetToDeleteSelected -> Removing : "
               << datasetQDir.absolutePath();

      // release the model relative to 'id'
      ReleaseDatasetModel( id );

      // remove the key from the map
      m_DatasetModels.remove( id );

      //  notify database changed
      emit DatabaseChanged();
      }

    // rmpath() removes the parent directory (i.e mvd2 ) when no files
    // (datasets ) in it ->  recreate "mvd2" if removed
    // TODO : find a better solution to replace this hack
    if (! datasetQDirParent.exists() )
      {
      qDebug() << this<< "::OnDatasetToDeleteSelected Making removed dir "
               << datasetQDirParent.absolutePath();
      datasetQDirParent.mkpath( datasetQDirParent.absolutePath() );
      }
    }
}

/*******************************************************************************/
void
DatabaseModel
::OnDatasetRenamed( const QString&  alias, const QString & id)
{
  // get the model relative to the previous key
  DatasetModel * datasetModel = FindDatasetModel(id);

  // update the alias
  datasetModel->SetAlias( alias );
}

} // end namespace 'mvd'
<commit_msg>ENH: use the dataset alias in the popup<commit_after>/*=========================================================================

  Program:   Monteverdi2
  Language:  C++

  Copyright (c) Centre National d'Etudes Spatiales. All rights reserved.
  See Copyright.txt for details.

  Monteverdi2 is distributed under the CeCILL licence version 2. See
  Licence_CeCILL_V2-en.txt or
  http://www.cecill.info/licences/Licence_CeCILL_V2-en.txt for more details.

  This software is distributed WITHOUT ANY WARRANTY; without even
  the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
  PURPOSE.  See the above copyright notices for more information.

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

#include "mvdDatabaseModel.h"

/*****************************************************************************/
/* INCLUDE SECTION                                                           */

//
// Qt includes (sorted by alphabetic order)
//// Must be included before system/custom includes.

//
// System includes (sorted by alphabetic order)

//
// ITK includes (sorted by alphabetic order)

//
// OTB includes (sorted by alphabetic order)

//
// Monteverdi includes (sorted by alphabetic order)
#include "mvdDatasetModel.h"
#include "mvdI18nApplication.h"

namespace mvd
{
/*
  TRANSLATOR mvd::DatabaseModel

  Necessary for lupdate to be aware of C++ namespaces.

  Context comment for translator.
*/

/*****************************************************************************/
/* CONSTANTS                                                                 */

/*****************************************************************************/
/* STATIC IMPLEMENTATION SECTION                                             */

/*****************************************************************************/
/* CLASS IMPLEMENTATION SECTION                                              */

/*******************************************************************************/
DatabaseModel
::DatabaseModel( QObject* parent ) :
  AbstractModel( parent ),
  m_DatasetModels(),
  m_SelectedDatasetModel( NULL )
{
}

/*******************************************************************************/
DatabaseModel
::~DatabaseModel()
{
}

/*******************************************************************************/
QStringList
DatabaseModel
::ListAvailableDatasets() const
{
  QDir cacheDir( I18nApplication::ConstInstance()->GetCacheDir() );

  QStringList nameFilters;
  nameFilters << QString( "*%1" ).arg( I18nApplication::DATASET_EXT );

  return cacheDir.entryList(
    nameFilters,
    QDir::Dirs | QDir::NoDotAndDotDot,
    QDir::Name
    );
}

/*******************************************************************************/
StringPairListType
DatabaseModel
::QueryDatasetModels() const
{
  StringPairListType   list;

  // need to send a list of pairs <alias, id> to know what is the
  // corresponding model to each alias in the WidgetTree
  DatasetModelMap::const_iterator it =  m_DatasetModels.begin();
  while( it != m_DatasetModels.end() )
    {
    // store alias <-> name
    StringPairType spair;
    spair.first = it.value()->GetAlias();
    spair.second = it.value()->GetName();

    // insert the pair in the list
    list.append( spair);
    ++it;
    }

  return list;
}

/*******************************************************************************/
DatasetModel*
DatabaseModel
::SelectDatasetModel( const DatasetId& id )
{
  qDebug() << this << "::SelectDatasetModel(" << id << ")";

  // Find dataset model or interrupt by exception.
  DatasetModel* datasetModel = FindDatasetModel( id );
  assert( datasetModel!=NULL );

  try
    {
    // Load dataset sub-models.
    datasetModel->LoadImageModels( -1, -1 );

    // If dataset model has been loaded, select it.
    SetSelectedDatasetModel( datasetModel );
    }
  catch( std::exception& exc )
    {
    throw exc;
    }

  // Return loaded and selected dataset model.
  return datasetModel;
}

/*******************************************************************************/
DatabaseModel::DatasetId
DatabaseModel
::RegisterDatasetModel( DatasetModel* model )
{
  assert( model!=NULL );

  // Construct DatasetId.
  DatasetId id( model->GetName() );

  // Find possible previously registerd dataset-model...
  DatasetModelMap::iterator it( m_DatasetModels.find( id ) );

  if( it!=m_DatasetModels.end() )
    {
    // BUGFIX: Clear selected dataset-model if it is to be deleted below.
    if( it.value()==m_SelectedDatasetModel )
      {
      SetSelectedDatasetModel( NULL );
      }

    // ...and destroy it.
    delete it.value();
    it.value() = NULL;
    }

  // Insert new dataset-model...
  it = m_DatasetModels.insert( id, model );

  // Re-parent dataset-model.
  model->setParent( this );

  // Signal model has changed.
  emit DatabaseChanged();

  // Return registered ID.
  return id;
}

/*******************************************************************************/
void
DatabaseModel
::ReleaseDatasetModel( const DatasetId& id )
{
  qDebug() << this << "::ReleaseDatasetModel(" << id << ")";

  // Find (key, value) pair.
  DatasetModelMap::iterator it( DatasetModelIterator( id ) );

  // release model
  delete it.value();
  it.value() = NULL;
}

/*******************************************************************************/
DatasetModel*
DatabaseModel
::NewDatasetModel( const DatasetId& id )
{
  qDebug() << this << "::NewDatasetModel(" << id << ")";

  // Find dataset model or interrupt by exception.
  DatasetModel* datasetModel = NULL;

  // Otherwise, load it from disk.
  try
    {
    // Create empty dataset model.
    datasetModel = new DatasetModel( this );

    // Build dataset model.
    assert( I18nApplication::ConstInstance() );

    DatasetModel::BuildContext context(
      I18nApplication::ConstInstance()->GetCacheDir().path(),
      id,
      id,
      false
    );

    datasetModel->BuildModel( &context );
    }

  catch( std::exception& exc )
    {
    // If loading was interrupted, delete allocated memory.
    delete datasetModel;
    datasetModel = NULL;

    // And forward interrupting exception.
    throw exc;
    }

  // Return loaded and selected dataset model.
  return datasetModel;
}

/*******************************************************************************/
void
DatabaseModel
::virtual_BuildModel( void* context )
{
  InitializeDatasetModels();
}

/*******************************************************************************/
void
DatabaseModel
::InitializeDatasetModels()
{
  QStringList datasets( ListAvailableDatasets() );

  ClearDatasetModels();

  for( QStringList::const_iterator it( datasets.begin() );
       it!=datasets.end();
       ++it )
    {
    try
      {
      DatasetModel* datasetModel = NewDatasetModel( *it );
      assert( datasetModel!=NULL );

      // by default alias == name
      m_DatasetModels.insert( datasetModel->GetName(), datasetModel );
      }
    catch( std::exception& exc )
      {
      throw exc;
      }
    }
}

/*******************************************************************************/
void
DatabaseModel
::ClearDatasetModels()
{
  while( !m_DatasetModels.empty() )
    {
    DatasetModelMap::iterator it( m_DatasetModels.begin() );

    delete it.value();
    it.value() = NULL;

    it = m_DatasetModels.erase( it );
    }
}

/*******************************************************************************/
/* SLOTS                                                                       */
/*******************************************************************************/
void
DatabaseModel
::OnDatasetToDeleteSelected( const QString&  id)
{
  // get the datasetModel to be deleted
  DatasetModel * model = FindDatasetModel( id );
  assert (model!=NULL);

  // pop up a Dialog widget to confirm the user choice
  QMessageBox msgBox;
  msgBox.setWindowTitle( tr( "Warning") );
  msgBox.setText(tr("You are about to remove the dataset : \n %1 \n\n"
                    " Are your sure ? ").arg( model->GetAlias() ) );
  msgBox.setStandardButtons(QMessageBox::Yes | QMessageBox::No);
  msgBox.setDefaultButton(QMessageBox::No);
  int ret = msgBox.exec();

  // if choice confirmed
  if (ret == QMessageBox::Yes)
    {
    qDebug() << this << " ::OnDatasetToDeleteSelected -> About to remove : "<< id;

    // if current selected item is removed, make the TreeWidget
    // focusing on the root item
    if (model  == GetSelectedDatasetModel() )
      {
      // set the Tree browser to point on nothing
      emit CurrentSelectedItemDeleted();

      //
      SetSelectedDatasetModel( NULL );
      }

    // get the full path to the dataset dir
    QDir datasetQDir(
      I18nApplication::Instance()->GetCacheDir().absolutePath() +
      "/" +
      id
      );
    QString datasetDir = datasetQDir.absolutePath();

    //
    // remove the files in this directory
    bool removingFilesStatus = true;
    QStringList fileList = datasetQDir.entryList( QDir::NoDotAndDotDot |  QDir::Files );
    for( int i = 0; i < fileList.count(); ++i )
      {
      qDebug()<< "Removing file "<< fileList.at(i);
      removingFilesStatus &= datasetQDir.remove( fileList.at(i) );
      }

    // go to parent dir
    QDir datasetQDirParent = datasetQDir;
    datasetQDirParent.cdUp();

    // if path removed successfuly :
    //  - release dataset model
    //  - notify change to update the database browser
    if ( removingFilesStatus &&  datasetQDirParent.rmpath( datasetDir ) )
      {
      qDebug() << this
               << " ::OnDatasetToDeleteSelected -> Removing : "
               << datasetQDir.absolutePath();

      // release the model relative to 'id'
      ReleaseDatasetModel( id );

      // remove the key from the map
      m_DatasetModels.remove( id );

      //  notify database changed
      emit DatabaseChanged();
      }

    // rmpath() removes the parent directory (i.e mvd2 ) when no files
    // (datasets ) in it ->  recreate "mvd2" if removed
    // TODO : find a better solution to replace this hack
    if (! datasetQDirParent.exists() )
      {
      qDebug() << this<< "::OnDatasetToDeleteSelected Making removed dir "
               << datasetQDirParent.absolutePath();
      datasetQDirParent.mkpath( datasetQDirParent.absolutePath() );
      }
    }
}

/*******************************************************************************/
void
DatabaseModel
::OnDatasetRenamed( const QString&  alias, const QString & id)
{
  // get the model relative to the previous key
  DatasetModel * datasetModel = FindDatasetModel(id);

  // update the alias
  datasetModel->SetAlias( alias );
}

} // end namespace 'mvd'
<|endoftext|>


<commit_before>#include <stdio.h>

#include <ros/ros.h>
#include <webrtc/base/ssladapter.h>
#include <webrtc/system_wrappers/include/trace.h>

#include "config.h"
#include "host.h"

#include <malloc.h>
#include <sys/resource.h>

struct Flush {

    Flush(Host& host) : host(host) {}

    void operator()(const ros::TimerEvent& event) {
        if (!ros::isShuttingDown()) {
            auto stats = host.flush();
            if (stats.reaped_data_messages) {
                ROS_INFO(
                    "flushed - reaped_data_messages=%zu",
                    stats.reaped_data_messages
                );
            }
        }
    }

    Host &host;

};

struct Reap {

    Reap(Host& host, double stale_threhold=30)
        : host(host),
          stale_threhold(stale_threhold) {
    }

    void operator()(const ros::TimerEvent& event) {
        if (!ros::isShuttingDown()) {
            auto stats = host.reap(stale_threhold);
            if (stats.deleted_connections) {
                ROS_INFO(
                    "reaped - deleted_connections=%zu",
                    stats.deleted_connections
                );
            }
        }
    }

    Host &host;
    double stale_threhold;

};

int main(int argc, char **argv) {
    ROS_INFO("initializing ros");
    ros::init(argc, argv, "host");

    ros::NodeHandle nh;

    ROS_INFO("loading config");
    Config config(Config::get(nh));

    if (!config.trace_file.empty()) {
        ROS_INFO(
            "setting webrtc trace file to %s w/ mask 0x%04x",
            config.trace_file.c_str(), config.trace_mask
        );
        webrtc::Trace::set_level_filter(config.trace_mask);
        webrtc::Trace::CreateTrace();
        webrtc::Trace::SetTraceFile(config.trace_file.c_str());
    }

    ROS_INFO("initializing ssl");
    if (!rtc::InitializeSSL()) {
        ROS_ERROR("ssl initialization failed");
        return 1;
    }

    struct rlimit corelimit = {0x70000000,0x70000000};
    if(setrlimit(RLIMIT_CORE,&corelimit) < 0) {
        ROS_ERROR("%s",strerror(errno));
        return 1;
    }
    struct rlimit aslimit = {0x70000000,0x70000000};
    if(setrlimit(RLIMIT_AS,&corelimit) < 0) {
        ROS_ERROR("%s",strerror(errno));
        return 1;
    }

    ROS_INFO("creating host");
    HostFactory host_factory;
    host_factory.audio_src = config.microphone;
    for (size_t i = 0; i != config.cameras.size(); i++) {
        host_factory.video_srcs.push_back(config.cameras[i]);
    }
    for (size_t i = 0; i != config.ice_servers.size(); i++) {
        host_factory.ice_servers.push_back(config.ice_servers[i]);
    }
    host_factory.pc_constraints = config.pc_constraints;
    host_factory.pc_bond_connect_timeout = config.pc_bond_connect_timeout;
    host_factory.pc_bond_heartbeat_timeout = config.pc_bond_heartbeat_timeout;
    host_factory.queue_sizes = config.queue_sizes;
    Host host = host_factory(nh);

    ROS_INFO("opening host ... ");
    if (!host.open(config.open_media_sources)) {
        ROS_INFO("host open failed");
        return 2;
    }
    ROS_INFO("opened host");

    Flush flush(host);
    ros::Timer flush_timer = nh.createTimer(
        ros::Duration(config.flush_frequency), flush
    );
    if (config.flush_frequency != 0) {
        ROS_INFO("scheduling host flush every %0.1f sec(s) ... ", config.flush_frequency);
        flush_timer.start();
    }

    Reap reap(host);
    ros::Timer reap_timer = nh.createTimer(
        ros::Duration(config.reap_frequency), reap
    );
    if (config.reap_frequency != 0) {
        ROS_INFO("scheduling host reap every %0.1f sec(s) ... ", config.reap_frequency);
        reap_timer.start();
    }

    ROS_INFO("start spinning");
    ros::spin();
    ROS_INFO("stop spinning");

    ROS_INFO("closing host ...");
    host.close();
    ROS_INFO("closed host");

    if (!config.trace_file.empty()) {
        ROS_INFO("resetting webrtc trace file");
        webrtc::Trace::SetTraceFile(NULL);
        webrtc::Trace::ReturnTrace();
    }

    return 0;
}
<commit_msg>PM-2187, relax the AS limit slightly to avoid a crash on first connect that is somtimes showing up. Tested that an induced leak still didn't OOM the whole system<commit_after>#include <stdio.h>

#include <ros/ros.h>
#include <webrtc/base/ssladapter.h>
#include <webrtc/system_wrappers/include/trace.h>

#include "config.h"
#include "host.h"

#include <malloc.h>
#include <sys/resource.h>

struct Flush {

    Flush(Host& host) : host(host) {}

    void operator()(const ros::TimerEvent& event) {
        if (!ros::isShuttingDown()) {
            auto stats = host.flush();
            if (stats.reaped_data_messages) {
                ROS_INFO(
                    "flushed - reaped_data_messages=%zu",
                    stats.reaped_data_messages
                );
            }
        }
    }

    Host &host;

};

struct Reap {

    Reap(Host& host, double stale_threhold=30)
        : host(host),
          stale_threhold(stale_threhold) {
    }

    void operator()(const ros::TimerEvent& event) {
        if (!ros::isShuttingDown()) {
            auto stats = host.reap(stale_threhold);
            if (stats.deleted_connections) {
                ROS_INFO(
                    "reaped - deleted_connections=%zu",
                    stats.deleted_connections
                );
            }
        }
    }

    Host &host;
    double stale_threhold;

};

int main(int argc, char **argv) {
    ROS_INFO("initializing ros");
    ros::init(argc, argv, "host");

    ros::NodeHandle nh;

    ROS_INFO("loading config");
    Config config(Config::get(nh));

    if (!config.trace_file.empty()) {
        ROS_INFO(
            "setting webrtc trace file to %s w/ mask 0x%04x",
            config.trace_file.c_str(), config.trace_mask
        );
        webrtc::Trace::set_level_filter(config.trace_mask);
        webrtc::Trace::CreateTrace();
        webrtc::Trace::SetTraceFile(config.trace_file.c_str());
    }

    ROS_INFO("initializing ssl");
    if (!rtc::InitializeSSL()) {
        ROS_ERROR("ssl initialization failed");
        return 1;
    }

    struct rlimit corelimit = {0x70000000,0x70000000};
    if(setrlimit(RLIMIT_CORE,&corelimit) < 0) {
        ROS_ERROR("%s",strerror(errno));
        return 1;
    }
    struct rlimit aslimit = {0xA0000000,0xA0000000};
    if(setrlimit(RLIMIT_AS,&corelimit) < 0) {
        ROS_ERROR("%s",strerror(errno));
        return 1;
    }

    ROS_INFO("creating host");
    HostFactory host_factory;
    host_factory.audio_src = config.microphone;
    for (size_t i = 0; i != config.cameras.size(); i++) {
        host_factory.video_srcs.push_back(config.cameras[i]);
    }
    for (size_t i = 0; i != config.ice_servers.size(); i++) {
        host_factory.ice_servers.push_back(config.ice_servers[i]);
    }
    host_factory.pc_constraints = config.pc_constraints;
    host_factory.pc_bond_connect_timeout = config.pc_bond_connect_timeout;
    host_factory.pc_bond_heartbeat_timeout = config.pc_bond_heartbeat_timeout;
    host_factory.queue_sizes = config.queue_sizes;
    Host host = host_factory(nh);

    ROS_INFO("opening host ... ");
    if (!host.open(config.open_media_sources)) {
        ROS_INFO("host open failed");
        return 2;
    }
    ROS_INFO("opened host");

    Flush flush(host);
    ros::Timer flush_timer = nh.createTimer(
        ros::Duration(config.flush_frequency), flush
    );
    if (config.flush_frequency != 0) {
        ROS_INFO("scheduling host flush every %0.1f sec(s) ... ", config.flush_frequency);
        flush_timer.start();
    }

    Reap reap(host);
    ros::Timer reap_timer = nh.createTimer(
        ros::Duration(config.reap_frequency), reap
    );
    if (config.reap_frequency != 0) {
        ROS_INFO("scheduling host reap every %0.1f sec(s) ... ", config.reap_frequency);
        reap_timer.start();
    }

    ROS_INFO("start spinning");
    ros::spin();
    ROS_INFO("stop spinning");

    ROS_INFO("closing host ...");
    host.close();
    ROS_INFO("closed host");

    if (!config.trace_file.empty()) {
        ROS_INFO("resetting webrtc trace file");
        webrtc::Trace::SetTraceFile(NULL);
        webrtc::Trace::ReturnTrace();
    }

    return 0;
}
<|endoftext|>


<commit_before>//=======================================================================
// Copyright (c) 2014-2018 Baptiste Wicht
// Distributed under the terms of the MIT License.
// (See accompanying file LICENSE or copy at
//  http://opensource.org/licenses/MIT)
//=======================================================================

/*!
 * \file vectorization.hpp
 * \brief Contains vectorization utilities for the vectorized assignments (done by the evaluator).
 *
 * This file automatically includes the correct header based on which vectorization utility is supported (AVX -> SSE -> NONE).
 */

#pragma once

#include <immintrin.h>

#include "etl/inline.hpp"

namespace etl {

/*!
 * \brief SIMD pack of some type, using a vector implementation type
 * \tparam V The vector implementation
 * \tparam T The real type
 * \tparam VT The vector type
 */
template <vector_mode_t V, typename T, typename VT>
struct simd_pack {
    using value_type     = T;  ///< The real value type
    using intrinsic_type = VT; ///< The used intrinsic type

    static constexpr vector_mode_t vector_mode = V; ///< The vector implementation mode

    intrinsic_type value; ///< The vector of value

    /*!
     * \brief Construct a new simd_pack around the given vector
     * \param value The vector value to build around
     */
    simd_pack(intrinsic_type value) : value(value) {
        // Nothing else to init
    }

    /*!
     * \brief Extract an element of the vector value
     * \param i The index of the element to get
     * \return The ith element from the vector
     */
    ETL_STRONG_INLINE(value_type) operator[](size_t i) const noexcept {
        return reinterpret_cast<const value_type*>(&value)[i];
    }
};

} // end of namespace etl

//Include al the vector implementation
#include "etl/avx512_vectorization.hpp"
#include "etl/avx_vectorization.hpp"
#include "etl/sse_vectorization.hpp"
#include "etl/no_vectorization.hpp"

namespace etl {

/*!
 * \brief Traits to get the intrinsic traits for a vector mode
 * \tparam V The vector mode
 */
template <vector_mode_t V>
struct get_intrinsic_traits {
    /*!
     * \brief The type of the intrinsic traits for T
     * \tparam T The type to get the intrinsic traits for
     */
    template <typename T>
    using type = no_intrinsic_traits<T>;
};

/*!
 * \brief Traits to get the vector implementation for a vector mode
 * \tparam V The vector mode
 */
template <vector_mode_t V>
struct get_vector_impl {
    using type = no_vec; ///< The vector implementation
};

#ifdef __AVX512F__

/*!
 * \brief get_intrinsic_traits for AVX-512
 */
template <>
struct get_intrinsic_traits<vector_mode_t::AVX512> {
    /*!
     * \brief The type of the intrinsic traits for T
     * \tparam T The type to get the intrinsic traits for
     */
    template <typename T>
    using type = avx512_intrinsic_traits<T>;
};

/*!
 * \copy get_vector_impl
 */
template <>
struct get_vector_impl<vector_mode_t::AVX512> {
    using type = avx512_vec; ///< The vector implementation
};

#endif

#ifdef __AVX__

/*!
 * \brief get_intrinsic_traits for AVX
 */
template <>
struct get_intrinsic_traits<vector_mode_t::AVX> {
    /*!
     * \brief The type of the intrinsic traits for T
     * \tparam T The type to get the intrinsic traits for
     */
    template <typename T>
    using type = avx_intrinsic_traits<T>;
};

/*!
 * \copy get_vector_impl
 */
template <>
struct get_vector_impl<vector_mode_t::AVX> {
    using type = avx_vec; ///< The vector implementation
};

#endif

#ifdef __SSE3__

/*!
 * \brief get_intrinsic_traits for SSE
 */
template <>
struct get_intrinsic_traits<vector_mode_t::SSE3> {
    /*!
     * \brief The type of the intrinsic traits for T
     * \tparam T The type to get the intrinsic traits for
     */
    template <typename T>
    using type = sse_intrinsic_traits<T>;
};

/*!
 * \copy get_vector_impl
 */
template <>
struct get_vector_impl<vector_mode_t::SSE3> {
    using type = sse_vec; ///< The vector implementation
};

#endif

#ifdef ETL_VECTORIZE_EXPR

#ifdef __AVX512F__

/*!
 * \brief The default vectorization scheme
 */
using default_vec = avx512_vec;

/*!
 * \brief The default intrinsic traits
 */
template <typename T>
using default_intrinsic_traits = avx512_intrinsic_traits<T>;

#elif defined(__AVX__)

/*!
 * \brief The default vectorization scheme
 */
using default_vec = avx_vec;

/*!
 * \brief The default intrinsic traits
 */
template <typename T>
using default_intrinsic_traits = avx_intrinsic_traits<T>;

#elif defined(__SSE3__)

/*!
 * \brief The default vectorization scheme
 */
using default_vec = sse_vec;

/*!
 * \brief The default intrinsic traits
 */
template <typename T>
using default_intrinsic_traits = sse_intrinsic_traits<T>;

#else

/*!
 * \brief The default vectorization scheme
 */
using default_vec = no_vec;

/*!
 * \brief The default intrinsic traits
 */
template <typename T>
using default_intrinsic_traits = no_intrinsic_traits<T>;

#endif //defined(__SSE__)

#else //ETL_VECTORIZE_EXPR

/*!
 * \brief The default vectorization scheme
 */
using default_vec = no_vec;

/*!
 * \brief The default intrinsic traits
 */
template <typename T>
using default_intrinsic_traits = no_intrinsic_traits<T>;

#endif //ETL_VECTORIZE_EXPR

/*!
 * \brief Helper to get the intrinsic corresponding type of a vectorizable type.
 */
template <typename T>
using default_intrinsic_type = typename default_intrinsic_traits<T>::intrinsic_type;

} //end of namespace etl
<commit_msg>Fix warning in GCC 7+<commit_after>//=======================================================================
// Copyright (c) 2014-2018 Baptiste Wicht
// Distributed under the terms of the MIT License.
// (See accompanying file LICENSE or copy at
//  http://opensource.org/licenses/MIT)
//=======================================================================

/*!
 * \file vectorization.hpp
 * \brief Contains vectorization utilities for the vectorized assignments (done by the evaluator).
 *
 * This file automatically includes the correct header based on which vectorization utility is supported (AVX -> SSE -> NONE).
 */

#pragma once

#include <immintrin.h>

#include "etl/inline.hpp"

namespace etl {

/*!
 * \brief SIMD pack of some type, using a vector implementation type
 * \tparam V The vector implementation
 * \tparam T The real type
 * \tparam VT The vector type
 */
template <vector_mode_t V, typename T, typename VT>
struct simd_pack {
    using value_type     = T;  ///< The real value type
    using intrinsic_type = VT; ///< The used intrinsic type

    static constexpr vector_mode_t vector_mode = V; ///< The vector implementation mode

    intrinsic_type value; ///< The vector of value

    /*!
     * \brief Construct a new simd_pack around the given vector
     * \param value The vector value to build around
     */
    simd_pack(intrinsic_type value) : value(value) {
        // Nothing else to init
    }

    /*!
     * \brief Extract an element of the vector value
     * \param i The index of the element to get
     * \return The ith element from the vector
     */
    ETL_STRONG_INLINE(value_type) operator[](size_t i) const noexcept {
        return reinterpret_cast<const value_type*>(&value)[i];
    }
};

} // end of namespace etl

#if defined __GNUC__ && __GNUC__>=6
#pragma GCC diagnostic ignored "-Wignored-attributes"
#endif

//Include al the vector implementation
#include "etl/avx512_vectorization.hpp"
#include "etl/avx_vectorization.hpp"
#include "etl/sse_vectorization.hpp"
#include "etl/no_vectorization.hpp"

#if defined __GNUC__ && __GNUC__>=6
#pragma GCC diagnostic pop
#endif

namespace etl {

/*!
 * \brief Traits to get the intrinsic traits for a vector mode
 * \tparam V The vector mode
 */
template <vector_mode_t V>
struct get_intrinsic_traits {
    /*!
     * \brief The type of the intrinsic traits for T
     * \tparam T The type to get the intrinsic traits for
     */
    template <typename T>
    using type = no_intrinsic_traits<T>;
};

/*!
 * \brief Traits to get the vector implementation for a vector mode
 * \tparam V The vector mode
 */
template <vector_mode_t V>
struct get_vector_impl {
    using type = no_vec; ///< The vector implementation
};

#ifdef __AVX512F__

/*!
 * \brief get_intrinsic_traits for AVX-512
 */
template <>
struct get_intrinsic_traits<vector_mode_t::AVX512> {
    /*!
     * \brief The type of the intrinsic traits for T
     * \tparam T The type to get the intrinsic traits for
     */
    template <typename T>
    using type = avx512_intrinsic_traits<T>;
};

/*!
 * \copy get_vector_impl
 */
template <>
struct get_vector_impl<vector_mode_t::AVX512> {
    using type = avx512_vec; ///< The vector implementation
};

#endif

#ifdef __AVX__

/*!
 * \brief get_intrinsic_traits for AVX
 */
template <>
struct get_intrinsic_traits<vector_mode_t::AVX> {
    /*!
     * \brief The type of the intrinsic traits for T
     * \tparam T The type to get the intrinsic traits for
     */
    template <typename T>
    using type = avx_intrinsic_traits<T>;
};

/*!
 * \copy get_vector_impl
 */
template <>
struct get_vector_impl<vector_mode_t::AVX> {
    using type = avx_vec; ///< The vector implementation
};

#endif

#ifdef __SSE3__

/*!
 * \brief get_intrinsic_traits for SSE
 */
template <>
struct get_intrinsic_traits<vector_mode_t::SSE3> {
    /*!
     * \brief The type of the intrinsic traits for T
     * \tparam T The type to get the intrinsic traits for
     */
    template <typename T>
    using type = sse_intrinsic_traits<T>;
};

/*!
 * \copy get_vector_impl
 */
template <>
struct get_vector_impl<vector_mode_t::SSE3> {
    using type = sse_vec; ///< The vector implementation
};

#endif

#ifdef ETL_VECTORIZE_EXPR

#ifdef __AVX512F__

/*!
 * \brief The default vectorization scheme
 */
using default_vec = avx512_vec;

/*!
 * \brief The default intrinsic traits
 */
template <typename T>
using default_intrinsic_traits = avx512_intrinsic_traits<T>;

#elif defined(__AVX__)

/*!
 * \brief The default vectorization scheme
 */
using default_vec = avx_vec;

/*!
 * \brief The default intrinsic traits
 */
template <typename T>
using default_intrinsic_traits = avx_intrinsic_traits<T>;

#elif defined(__SSE3__)

/*!
 * \brief The default vectorization scheme
 */
using default_vec = sse_vec;

/*!
 * \brief The default intrinsic traits
 */
template <typename T>
using default_intrinsic_traits = sse_intrinsic_traits<T>;

#else

/*!
 * \brief The default vectorization scheme
 */
using default_vec = no_vec;

/*!
 * \brief The default intrinsic traits
 */
template <typename T>
using default_intrinsic_traits = no_intrinsic_traits<T>;

#endif //defined(__SSE__)

#else //ETL_VECTORIZE_EXPR

/*!
 * \brief The default vectorization scheme
 */
using default_vec = no_vec;

/*!
 * \brief The default intrinsic traits
 */
template <typename T>
using default_intrinsic_traits = no_intrinsic_traits<T>;

#endif //ETL_VECTORIZE_EXPR

/*!
 * \brief Helper to get the intrinsic corresponding type of a vectorizable type.
 */
template <typename T>
using default_intrinsic_type = typename default_intrinsic_traits<T>::intrinsic_type;

} //end of namespace etl
<|endoftext|>