diff --git a/Frontend Angular 4/src/app/app.module.ts b/Frontend Angular 4/src/app/app.module.ts
index 7cac3deb343446316fb9671c625072fa24869fb5..51ad01f17fe31eb997e7f6d9d12614e283de2a74 100755
--- a/Frontend Angular 4/src/app/app.module.ts	
+++ b/Frontend Angular 4/src/app/app.module.ts	
@@ -7,11 +7,11 @@ import { AppComponent } from './app.component';
 import { AuthGuard } from './shared/guards/auth.guard';
 import { SessionService } from './shared/services/session.service';
 import { NotificacionService } from './shared/services/notificacion.service';
-import {NotificacionModule} from './notificacion/notificacion.module'
+import {NotificacionModule} from './notificacion/notificacion.module';
 
 @NgModule({
     declarations: [
-        AppComponent,
+        AppComponent
     ],
     imports: [
         NotificacionModule,
diff --git a/Frontend Angular 4/src/app/layout/layout.module.ts b/Frontend Angular 4/src/app/layout/layout.module.ts
index 9777481aaa12a918ec469c807b12d4c1338c7cc5..ab31a0b0ed8846dc4d4c027eafd5e409384201e8 100755
--- a/Frontend Angular 4/src/app/layout/layout.module.ts	
+++ b/Frontend Angular 4/src/app/layout/layout.module.ts	
@@ -23,7 +23,7 @@ import { NotificacionModule } from '../notificacion/notificacion.module';
     declarations: [
         LayoutComponent,
         HeaderComponent,
-        SidebarComponent
+        SidebarComponent        
     ],
     providers: [AuthenticationService, HaskellService]
 })
diff --git a/Frontend Angular 4/src/app/layout/matefun/codemirror/matefun-mode-EN.js b/Frontend Angular 4/src/app/layout/matefun/codemirror/matefun-mode-EN.js
new file mode 100644
index 0000000000000000000000000000000000000000..7bf015b380048b83c878b197b18d47e0c5931b4b
--- /dev/null
+++ b/Frontend Angular 4/src/app/layout/matefun/codemirror/matefun-mode-EN.js	
@@ -0,0 +1,258 @@
+(function(mod) {
+  if (typeof exports == "object" && typeof module == "object") // CommonJS
+    mod(require("codemirror/lib/codemirror"));
+  else if (typeof define == "function" && define.amd) // AMD
+    define(["codemirror/lib/codemirror"], mod);
+  else // Plain browser env
+    mod(CodeMirror);
+})(function(CodeMirror) {
+  "use strict";
+
+  CodeMirror.defineMode("matefun-EN", function(_config, modeConfig) {
+
+    function switchState(source, setState, f) {
+      setState(f);
+      return f(source, setState);
+    }
+
+    var smallRE = /[a-z_]/;
+    var largeRE = /[A-Z]/;
+    var digitRE = /\d/;
+    var hexitRE = /[0-9A-Fa-f]/;
+    var octitRE = /[0-7]/;
+    var idRE = /[a-z_A-Z0-9'\xa1-\uffff]/;
+    var symbolRE = /[-!#$%&*+.\/<=>?@\\^|~:]/;
+    var specialRE = /[(),;[\]`{}]/;
+  var whiteCharRE = /[ \t\v\f]/; // newlines are handled in tokenizer
+
+  function normal(source, setState) {
+    if (source.eatWhile(whiteCharRE)) {
+      return null;
+    }
+
+    var ch = source.next();
+    if (specialRE.test(ch)) {
+      if (ch == '{' && source.eat('-')) {
+        var t = "comment";
+        if (source.eat('#')) {
+          t = "meta";
+        }
+        return switchState(source, setState, ncomment(t, 1));
+      }
+      return null;
+    }
+
+    if (ch == '\'') {
+      if (source.eat('\\')) {
+        source.next();  // should handle other escapes here
+      }
+      else {
+        source.next();
+      }
+      if (source.eat('\'')) {
+        return "string";
+      }
+      return "string error";
+    }
+
+    if (ch == '"') {
+      return switchState(source, setState, stringLiteral);
+    }
+
+    if (largeRE.test(ch)) {
+      source.eatWhile(idRE);
+      if (source.eat('.')) {
+        return "qualifier";
+      }
+      return "variable-2";
+    }
+
+    if (smallRE.test(ch)) {
+      source.eatWhile(idRE);
+      return "variable";
+    }
+
+    if (digitRE.test(ch)) {
+      if (ch == '0') {
+        if (source.eat(/[xX]/)) {
+          source.eatWhile(hexitRE); // should require at least 1
+          return "integer";
+        }
+        if (source.eat(/[oO]/)) {
+          source.eatWhile(octitRE); // should require at least 1
+          return "number";
+        }
+      }
+      source.eatWhile(digitRE);
+      var t = "number";
+      if (source.match(/^\.\d+/)) {
+        t = "number";
+      }
+      if (source.eat(/[eE]/)) {
+        t = "number";
+        source.eat(/[-+]/);
+        source.eatWhile(digitRE); // should require at least 1
+      }
+      return t;
+    }
+
+    if (ch == "." && source.eat("."))
+      return "keyword";
+
+    if (symbolRE.test(ch)) {
+      if (ch == '-' && source.eat(/-/)) {
+        source.eatWhile(/-/);
+        if (!source.eat(symbolRE)) {
+          source.skipToEnd();
+          return "comment";
+        }
+      }
+      var t = "variable";
+      if (ch == ':') {
+        t = "variable-2";
+      }
+      source.eatWhile(symbolRE);
+      return t;
+    }
+
+    return "error";
+  }
+
+  function ncomment(type, nest) {
+    if (nest == 0) {
+      return normal;
+    }
+    return function(source, setState) {
+      var currNest = nest;
+      while (!source.eol()) {
+        var ch = source.next();
+        if (ch == '{' && source.eat('-')) {
+          ++currNest;
+        }
+        else if (ch == '-' && source.eat('}')) {
+          --currNest;
+          if (currNest == 0) {
+            setState(normal);
+            return type;
+          }
+        }
+      }
+      setState(ncomment(type, currNest));
+      return type;
+    };
+  }
+
+  function stringLiteral(source, setState) {
+    while (!source.eol()) {
+      var ch = source.next();
+      if (ch == '"') {
+        setState(normal);
+        return "string";
+      }
+      if (ch == '\\') {
+        if (source.eol() || source.eat(whiteCharRE)) {
+          setState(stringGap);
+          return "string";
+        }
+        if (source.eat('&')) {
+        }
+        else {
+          source.next(); // should handle other escapes here
+        }
+      }
+    }
+    setState(normal);
+    return "string error";
+  }
+
+  function stringGap(source, setState) {
+    if (source.eat('\\')) {
+      return switchState(source, setState, stringLiteral);
+    }
+    source.next();
+    setState(normal);
+    return "error";
+  }
+
+
+  var wellKnownWords = (function() {
+    var wkw = {};
+    function setType(t) {
+      return function () {
+        for (var i = 0; i < arguments.length; i++)
+          wkw[arguments[i]] = t;
+      };
+    }
+
+    setType("keyword")(
+     "include"
+     ,"set","in"
+     ,"if", "or" 
+     ,"isEmpty");
+
+    setType("keyword")("<-", "->");
+
+    setType("builtin")("-", "+", "*", "/","^","!",":","==","/=","<",">","<=",">=","::","->","X","|");
+
+    //tipos predefinidos
+    setType("builtin")("Red", "Green", "Blue", "Black","White","Gray","Yellow","FigEmpty", "[]"
+      ,"R", "Fig", "Fig3D", "Color", "color3D", "join3D", "rotate3D", "move3D"
+      );
+
+    setType("builtin")(
+      "abs", "acos", "acosh", "all", "and", "any", "appendFile", "asTypeOf",
+      "asin", "asinh", "atan", "atan2", "atanh", "break", "catch", "ceiling",
+      "compare", "concat", "concatMap", "const", "cos", "cosh", "curry",
+      "cycle", "decodeFloat", "div", "divMod", "drop", "dropWhile", "either",
+      "elem", "encodeFloat", "enumFrom", "enumFromThen", "enumFromThenTo",
+      "enumFromTo", "error", "even", "exp", "exponent", "fail", "filter",
+      "flip", "floatDigits", "floatRadix", "floatRange", "floor", "fmap",
+      "foldl", "foldl1", "foldr", "foldr1", "fromEnum", "fromInteger",
+      "fromIntegral", "fromRational", "fst", "gcd", "getChar", "getContents",
+      "getLine", "head", "id", "init", "interact", "ioError", "isDenormalized",
+      "isIEEE", "isInfinite", "isNaN", "isNegativeZero", "iterate", "last",
+      "lcm", "length", "lex", "lines", "log", "logBase", "lookup", "map",
+      "mapM", "mapM_", "max", "maxBound", "maximum", "maybe", "min", "minBound",
+      "minimum", "mod", "negate", "not", "notElem", "null", "odd", "or",
+      "otherwise", "pi", "pred", "print", "product", "properFraction",
+      "putChar", "putStr", "putStrLn", "quot", "quotRem", "read", "readFile",
+      "readIO", "readList", "readLn", "readParen", "reads", "readsPrec",
+      "realToFrac", "recip", "rem", "repeat", "replicate", "return", "reverse",
+      "round", "scaleFloat", "scanl", "scanl1", "scanr", "scanr1", "seq",
+      "sequence", "sequence_", "show", "showChar", "showList", "showParen",
+      "showString", "shows", "showsPrec", "significand", "signum", "sin",
+      "sinh", "snd", "span", "splitAt", "sqrt", "subtract", "succ", "sum",
+      "tail", "take", "takeWhile", "tan", "tanh", "toEnum", "toInteger",
+      "toRational", "truncate", "uncurry", "undefined", "unlines", "until",
+      "unwords", "unzip", "unzip3", "userError", "words", "writeFile", "zip",
+      "zip3", "zipWith", "zipWith3");
+
+    var override = modeConfig.overrideKeywords;
+    if (override) for (var word in override) if (override.hasOwnProperty(word))
+      wkw[word] = override[word];
+
+    return wkw;
+  })();
+
+
+
+  return {
+    startState: function ()  { return { f: normal }; },
+    copyState:  function (s) { return { f: s.f }; },
+
+    token: function(stream, state) {
+      var t = state.f(stream, function(s) { state.f = s; });
+      var w = stream.current();
+      return wellKnownWords.hasOwnProperty(w) ? wellKnownWords[w] : t;
+    },
+
+    blockCommentStart: "{-",
+    blockCommentEnd: "-}",
+    lineComment: "--"
+  };
+
+});
+
+CodeMirror.defineMIME("text/x-matefun", "matefun-EN");
+
+});
\ No newline at end of file
diff --git a/Frontend Angular 4/src/app/layout/matefun/codemirror-matefun-mode.js b/Frontend Angular 4/src/app/layout/matefun/codemirror/matefun-mode-ES.js
similarity index 98%
rename from Frontend Angular 4/src/app/layout/matefun/codemirror-matefun-mode.js
rename to Frontend Angular 4/src/app/layout/matefun/codemirror/matefun-mode-ES.js
index 04de0e3657f5f1974083586be914cdcacbd91f82..72c0d89e0c93de1b29bda44673535033def1987e 100755
--- a/Frontend Angular 4/src/app/layout/matefun/codemirror-matefun-mode.js	
+++ b/Frontend Angular 4/src/app/layout/matefun/codemirror/matefun-mode-ES.js	
@@ -8,7 +8,7 @@
 })(function(CodeMirror) {
   "use strict";
 
-  CodeMirror.defineMode("matefun", function(_config, modeConfig) {
+  CodeMirror.defineMode("matefun-ES", function(_config, modeConfig) {
 
     function switchState(source, setState, f) {
       setState(f);
@@ -256,6 +256,6 @@
 
 });
 
-CodeMirror.defineMIME("text/x-matefun", "matefun");
+CodeMirror.defineMIME("text/x-matefun", "matefun-ES");
 
 });
\ No newline at end of file
diff --git a/Frontend Angular 4/src/app/layout/matefun/matefun.component.ts b/Frontend Angular 4/src/app/layout/matefun/matefun.component.ts
index ac12c4a9e3fb1d881e30409af5e08edd6ebdcadd..cbd3981ffcfb5b69202e6fdbec347c2dbfd97591 100755
--- a/Frontend Angular 4/src/app/layout/matefun/matefun.component.ts	
+++ b/Frontend Angular 4/src/app/layout/matefun/matefun.component.ts	
@@ -40,7 +40,8 @@ import 'codemirror/addon/search/matchesonscrollbar';
 import 'codemirror/addon/search/jump-to-line';
 import 'codemirror/addon/edit/matchbrackets';
 
-import './codemirror-matefun-mode.js'
+import './codemirror/matefun-mode-ES.js'
+import './codemirror/matefun-mode-EN.js'
 
 var codeMirrorRef:any;
 var componentRef : any;
@@ -80,7 +81,7 @@ export class MateFunComponent {
         matchBrackets: true,
         extraKeys: {"Ctrl-Space": "autocomplete"},
         mode: {
-            name: "matefun", 
+            name: "matefun-EN", 
             globalVars: true
         },
         gutters: ["CodeMirror-linenumbers", "breakpoints"],
diff --git a/Frontend Angular 4/src/app/layout/plotter/graph3D/graph3D.component.html b/Frontend Angular 4/src/app/layout/plotter/graph3D/graph3D.component.html
index add6d7dd261f15de139eaca8227babb68c7d6381..4a6e68d041853e4501fe637ffd157e2e8abc5bcc 100644
--- a/Frontend Angular 4/src/app/layout/plotter/graph3D/graph3D.component.html	
+++ b/Frontend Angular 4/src/app/layout/plotter/graph3D/graph3D.component.html	
@@ -1,93 +1,205 @@
 <div class="card">
-    <div class="controls">
-			<div class="btn-group ddown">
-				<button 
-					type="button" 
-					class="btn btn-secondary"
-					style="min-width: 70px;"
-					(click)=changeZoomType()
-				>
-					{{getZoom3DTypeName(zoomType)}}
-				</button>
-				<div class="btn-group" ngbDropdown role="group" aria-label="Button group with nested dropdown">
-					<button class="btn btn-secondary dropdown-toggle-split" ngbDropdownToggle></button>
-					<div class="dropdown-menu" ngbDropdownMenu>
-						<button 
-							*ngFor="let type of [1,2,3,4]" 
-							class="dropdown-item"
-							[disabled]="type === zoomType"
-							(click)=changeZoomType(type)
-						>
-							{{getZoom3DTypeName(type)}}
-						</button>
-					</div>
-				</div>
-			</div> 
-
+	<div class="controls">
+		<div class="btn-group ddown">
 			<button 
-				ngbPopover="Zoom +"  
-				triggers="mouseenter:mouseleave" 
-				data-placement="bottom" 
-				class="btn btn-sm btn-secondary" 
-				(click)=zoomIn() 
+				type="button" 
+				class="btn btn-secondary"
+				style="min-width: 70px;"
+				(click)=changeZoomType()
 			>
-				<i class="fa fa-plus"></i>
+				{{getZoom3DTypeName(graphProps.zoomType)}}
 			</button>
+			<div class="btn-group" ngbDropdown role="group" aria-label="Button group with nested dropdown">
+				<button class="btn btn-secondary dropdown-toggle-split" ngbDropdownToggle></button>
+				<div class="dropdown-menu" ngbDropdownMenu>
+					<button 
+						*ngFor="let type of [1,2,3,4]" 
+						class="dropdown-item"
+						[disabled]="type === graphProps.zoomType"
+						(click)=changeZoomType(type)
+					>
+						{{getZoom3DTypeName(type)}}
+					</button>
+				</div>
+			</div>
+		</div> 
 
-			<button 
-				ngbPopover="Zoom -"  
-				triggers="mouseenter:mouseleave" 
-				data-placement="bottom" 
-				class="btn btn-sm btn-secondary" 
-				(click)=zoomOut() 
-			>
-				<i class="fa fa-minus"></i>
-			</button>
+		<button 
+			ngbPopover="Zoom +"  
+			triggers="mouseenter:mouseleave" 
+			data-placement="bottom" 
+			class="btn btn-sm btn-secondary" 
+			(click)=zoomIn() 
+		>
+			<i class="fa fa-plus"></i>
+		</button>
 
-			<button 
-				ngbPopover="Centrar"  
-				triggers="mouseenter:mouseleave" 
-				data-placement="bottom" 
-				class="btn btn-sm btn-secondary" 
-				(click)=zoomMas() 
-			>
-				<i class="fa fa-arrows"></i>
-			</button>
+		<button 
+			ngbPopover="Zoom -"  
+			triggers="mouseenter:mouseleave" 
+			data-placement="bottom" 
+			class="btn btn-sm btn-secondary" 
+			(click)=zoomOut() 
+		>
+			<i class="fa fa-minus"></i>
+		</button>
 
-			<button 
-				ngbPopover="Borrar"  
-				triggers="mouseenter:mouseleave" 
-				data-placement="bottom" 
-				class="btn btn-sm btn-secondary" 
-				(click)=zoomMas() 
-			>
-				<i class="fa fa-trash"></i>
-			</button>
+		<button 
+			ngbPopover="Centrar"  
+			triggers="mouseenter:mouseleave" 
+			data-placement="bottom" 
+			class="btn btn-sm btn-secondary" 
+			(click)=center() 
+		>
+			<i class="fa fa-arrows"></i>
+		</button>
 
-			<button 
-			ngbPopover="Configuración"  
+		<button 
+			closePopoverOnOutsideClick
+			class="btn btn-sm btn-secondary" 
+			placement="bottom" 
+			[ngbPopover]=popoverAxesSize
+			popoverTitle="Rango de ejes"
+			#popover="ngbPopover"
+			tiggers="click"
+		>
+			<i class="fa fa-arrows-h"></i>
+		</button>
+		<ng-template #popoverAxesSize>
+			<div class="axes-size">
+				<div class="axe">
+					<input 
+						type="number" 
+						class="form-control form-control-sm" 
+						[(ngModel)]="graphProps.range.xMin"
+						[max]="graphProps.range.xMax-1"
+						[min]="-99" 
+						(change)="onChangeAxesSize('xMin', $event)"
+					/>
+					<div class="less-than">
+						<span>&#8804;</span>x<span>&#8804;</span>
+					</div>
+					
+					<input 
+						type="number" 
+						class="form-control form-control-sm" 
+						[(ngModel)]="graphProps.range.xMax"
+						[max]="99"
+						[min]="graphProps.range.xMin+1" 
+						(change)="onChangeAxesSize('xMax', $event)"
+					/>
+				</div>
+
+				<div class="axe">
+					<input 
+						type="number" 
+						class="form-control form-control-sm" 
+						[(ngModel)]="graphProps.range.yMin"
+						[max]="graphProps.range.yMax-1"
+						[min]="-99" 
+						(change)="onChangeAxesSize('yMin', $event)"
+					/>
+					<div class="less-than">
+						<span>&#8804;</span>y<span>&#8804;</span>
+					</div>
+					
+					<input 
+						type="number" 
+						class="form-control form-control-sm" 
+						[(ngModel)]="graphProps.range.yMax"
+						[max]="99"
+						[min]="graphProps.range.yMin+1" 
+						(change)="onChangeAxesSize('yMax', $event)"
+					/>
+				</div>
+
+				<div class="axe">
+					<input 
+						type="number" 
+						class="form-control form-control-sm" 
+						[(ngModel)]="graphProps.range.zMin"
+						[max]="graphProps.range.zMax-1"
+						[min]="-99" 
+						(change)="onChangeAxesSize('zMin', $event)"
+					/>
+					<div class="less-than">
+						<span>&#8804;</span>z<span>&#8804;</span>
+					</div>
+					
+					<input 
+						type="number" 
+						class="form-control form-control-sm" 
+						[(ngModel)]="graphProps.range.zMax"
+						[max]="99"
+						[min]="graphProps.range.zMin+1" 
+						(change)="onChangeAxesSize('zMax', $event)"
+					/>
+				</div>
+			</div>
+		</ng-template>
+		
+
+		<button 
+			ngbPopover="Borrar"  
 			triggers="mouseenter:mouseleave" 
 			data-placement="bottom" 
 			class="btn btn-sm btn-secondary" 
-			(click)=zoomMas() 
+			(click)=clear() 
+		>
+			<i class="fa fa-trash"></i>
+		</button>
+
+		<button 
+		[ngbPopover]=popoverConfig
+			closePopoverOnOutsideClick
+			placement="bottom" 
+		
+			tiggers="click"
+			class="btn btn-sm btn-secondary" 
+			popoverTitle="Configuración"
 		>
 			<i class="fa fa-gear"></i>
 		</button>
- 		
+
+		<ng-template #popoverConfig>
+			<div style="width: 140px;">
+				<label class="d-block">
+					<input type="checkbox"[checked]=graphProps.showAxes (click)="changeAxesVisibility()">
+					Mostrar grilla
+				</label>
+
+				<div style="display: flex;">
+					<span style="margin-right: 8px; align-self: center;">
+						Quality:
+					</span>
+
+					<input 
+						type="number" 
+						class="form-control form-control-sm" 
+						[(ngModel)]="graphProps.quality"
+						[max]="99"
+						[min]="2" 
+						(change)="onChangeQuality()"
+						style="width: 55px;"
+					/>
+				</div>
+			</div>
+		</ng-template>
+
+	
 	</div>
 		
 	<div class="card-block contenedor-canvas" >
 		<animation-control
 			[minSpeed]="60"
-			[value]="animation.value"
-			[speed]="animation.speed"
-			[visible]="animation.visible"
-			[playing]="animation.playing"
+			[value]="animationProps.value"
+			[speed]="animationProps.speed"
+			[visible]="animationProps.visible"
+			[playing]="animationProps.playing"
 			[onChangeSpeed]="onAnimationChangeSpeed"
 			[onTogglePlay]="onAnimationTogglePlay"
 		>
 		</animation-control>
-
 		
 		<div #graph3DElement style="width: 100%; height: 100%;">
 		</div>
diff --git a/Frontend Angular 4/src/app/layout/plotter/graph3D/graph3D.component.scss b/Frontend Angular 4/src/app/layout/plotter/graph3D/graph3D.component.scss
index 9b83024218ee13a319457d3e9af18e2f1092e8f9..fe06fa38773fd14c43c00fb1628da017e7846297 100644
--- a/Frontend Angular 4/src/app/layout/plotter/graph3D/graph3D.component.scss	
+++ b/Frontend Angular 4/src/app/layout/plotter/graph3D/graph3D.component.scss	
@@ -14,7 +14,25 @@
 		vertical-align: bottom;
 
 		button {
-			padding: 2.5px 5px;
+			padding: 2.5px 8px 2.5px 3px;
+		}
+	}
+
+	.axes-size {
+		width: 165px;
+
+		.axe {
+			display: flex;
+
+			&:not(:last-child) {
+				margin-bottom: 6px;
+			}
+
+			.less-than {
+				padding: 0 2.5px 0 5px;
+				font-size: 17px; 
+				letter-spacing: 4px;
+			}
 		}
 	}
 }
@@ -22,4 +40,8 @@
 .dropdown-item:disabled{
 	background-color: #f7f7f7;
 	color: #9e9e9e;
+}
+
+.d-block{
+	display: block;
 }
\ No newline at end of file
diff --git a/Frontend Angular 4/src/app/layout/plotter/graph3D/graph3D.component.ts b/Frontend Angular 4/src/app/layout/plotter/graph3D/graph3D.component.ts
index 532dcdd28606ab972dd90b7152efb8d298198cf1..f4713fcba3a9a2059f71c0b40a67e376a52e6389 100644
--- a/Frontend Angular 4/src/app/layout/plotter/graph3D/graph3D.component.ts	
+++ b/Frontend Angular 4/src/app/layout/plotter/graph3D/graph3D.component.ts	
@@ -1,7 +1,7 @@
 import { Component, OnInit, ViewChild, ElementRef, NgZone } from '@angular/core';
 import * as graph3DLib from 'graph3d';
 import { GHCIService } from '../../../shared/services/ghci.service';
-import { formatJSON, AnimationProps, Zoom3DType } from './graph3D.helper';
+import { formatJSON, AnimationProps, Zoom3DType, GraphProps, Default_GraphProps, debounce } from './graph3D.helper';
 
 @Component({
   selector: 'graph3d-component',
@@ -11,23 +11,24 @@ import { formatJSON, AnimationProps, Zoom3DType } from './graph3D.helper';
     '(window:resize)': 'onResize($event)'
   }
 })
-export class Graph3DComponent implements OnInit {
+export class Graph3DComponent  {
 
   private ghciServiceSub: any;
 
   @ViewChild('graph3DElement') 
   private graph3DRef: ElementRef;
 
-  public zoomType: Zoom3DType = Zoom3DType.Normal;
-
-  private animation : AnimationProps = {
+  private graphProps : GraphProps = Default_GraphProps;
+  
+  private animationProps : AnimationProps = {
     visible: false,
     playing: false,
     value: 0,
     speed: 1000
   };
+  
 
-  constructor(private ghciService: GHCIService, private zone: NgZone) {
+  constructor(ghciService: GHCIService, private zone: NgZone) {
     this.ghciServiceSub = ghciService.messages.subscribe(
       message => {
         if (message.tipo == "canvas3D") {
@@ -38,12 +39,13 @@ export class Graph3DComponent implements OnInit {
         else if (message.tipo == "animacion3D") {
           const frames = message.resultado.map((frame) => JSON.parse(formatJSON(frame)));
 
-          this.animation.visible = true;
-          this.animation.playing = true;
-          this.animation.value = 0;
+          this.animationProps.visible = true;
+          this.animationProps.playing = true;
+          this.animationProps.value = 0;
 
+          graph3DLib.clear();
           graph3DLib.initializeAnimation(frames, 
-            (value) => this.animation.value = value
+            (value) => this.animationProps.value = value
           );
 
           graph3DLib.playAnimation();
@@ -52,10 +54,10 @@ export class Graph3DComponent implements OnInit {
     )
   }
 
-  ngOnInit() {
-    this.zone.runOutsideAngular(() => {
+  ngAfterViewInit() {
+  //  this.zone.runOutsideAngular(() => {
       graph3DLib.initialize(this.graph3DRef.nativeElement);
-    })
+    //})
   }
 
   ngOnDestroy() {
@@ -71,30 +73,76 @@ export class Graph3DComponent implements OnInit {
   }
 
   onAnimationChangeSpeed = (value) => {
-    this.animation.speed = parseInt(value);
+    this.animationProps.speed = parseInt(value);
     graph3DLib.changeSpeedAnimation(parseInt(value));
   }
 
   onAnimationTogglePlay = () => {
-    if (this.animation.playing) {
+    if (this.animationProps.playing) {
       graph3DLib.pauseAnimation();
     }
     else {
       graph3DLib.playAnimation();
     }
     
-    this.animation.playing = !this.animation.playing;
+    this.animationProps.playing = !this.animationProps.playing;
   }
 
   public changeZoomType = (type: Zoom3DType = null) => {
     if (type != null) {
-      this.zoomType = type;
+      this.graphProps.zoomType = type;
+    } 
+    else {
+      this.graphProps.zoomType = (this.graphProps.zoomType % 4) + 1;
+    }
+
+    graph3DLib.changeZoomType(this.graphProps.zoomType);
+  }
+
+  public changeAxesVisibility = () => {
+    this.graphProps.showAxes = !this.graphProps.showAxes;
+    graph3DLib.showAxes(this.graphProps.showAxes);
+  }
+
+  handleAxesRangeDebounced = debounce(function () {
+    setTimeout(() =>
+      graph3DLib.changeAxesSize(this.graphProps.range)
+    );
+  }, 500);
+  
+  public onChangeAxesSize = (v, event) => {
+    let value = this.graphProps.range[v];
+
+    const min = parseInt(event.target.min);
+    const max = parseInt(event.target.max);
+
+    if (value == null) {
+      value = v.search('Min') ? min : max;
+      this.graphProps.range[v] = value;
+    }
+
+    if (value < min) {
+      this.graphProps.range[v] = min;
+    } 
+    
+    if (value > max) {
+      this.graphProps.range[v] = max;
+    }
+    this.handleAxesRangeDebounced();
+    //graph3DLib.changeAxesSize(this.graphProps.range)
+  }
+
+  public onChangeQuality = () => {
+    const value = this.graphProps.quality;
+
+    if (value == null || value <= 1) {
+      this.graphProps.quality = 30;
     } 
     else {
-      this.zoomType = (this.zoomType % 4) + 1;
+      this.graphProps.quality = value;
     }
 
-    graph3DLib.changeZoomType(this.zoomType);
+    graph3DLib.changeOptions({quality: value});
   }
 
   public zoomIn = () => {
@@ -105,6 +153,18 @@ export class Graph3DComponent implements OnInit {
     graph3DLib.changeZoom(false);
   }
   
+  public clear = () => {
+    this.animationProps.visible = false;
+
+    graph3DLib.clear();
+  }
+  
+  public center = () => {
+    this.graphProps = Default_GraphProps;
+
+    graph3DLib.reset();
+  }
+
   public getZoom3DTypeName = (type: Zoom3DType) => {
     switch (type) {
       case Zoom3DType.Normal:
diff --git a/Frontend Angular 4/src/app/layout/plotter/graph3D/graph3D.helper.ts b/Frontend Angular 4/src/app/layout/plotter/graph3D/graph3D.helper.ts
index a13ebd2ae34cd8178453a508a3889358d621496a..eef025d8a8d6ce443b8ab15c0f95479e566f9046 100644
--- a/Frontend Angular 4/src/app/layout/plotter/graph3D/graph3D.helper.ts	
+++ b/Frontend Angular 4/src/app/layout/plotter/graph3D/graph3D.helper.ts	
@@ -1,13 +1,21 @@
 export function formatJSON(jsonString: string) : string {
 	const regexRot = /\"rot\"\:\((\d*.\d*),(\d*.\d*),(\d*.\d*)\)/g;
+	const regexPts = /\"pts\"\:\[\((\-?\d*.\d*),(\-?\d*.\d*),(\-?\d*.\d*)\),\((\-?\d*.\d*),(\-?\d*.\d*),(\-?\d*.\d*)\)\]/g;
 
-	return jsonString.replace(
-		regexRot, (match, x, y, z) => {
-			return `"rot": { "x": ${x}, "y": ${y}, "z": ${z} }`
-		}
-	)
+	return jsonString
+		.replace(
+			regexRot, (match, x, y, z) => {
+				return `"rot": { "x": ${x}, "y": ${y}, "z": ${z} }`
+			}
+		)
+		.replace(
+			regexPts, (match, x1, y1, z1, x2, y2, z2) => {
+				return `"pts": [{ "x": ${x1}, "y": ${y1}, "z": ${z1} },{ "x": ${x2}, "y": ${y2}, "z": ${z2} }]`
+			}
+		)
 }
 
+
 export interface AnimationProps {
 	visible?: boolean,
 	playing?: boolean,
@@ -22,3 +30,42 @@ export enum Zoom3DType {
 	ZAxis,
 }
 
+export interface GraphProps {
+	zoomType?: Zoom3DType,
+	showAxes?: boolean,
+	quality?: number,
+	range: {
+		xMin?: number,
+		xMax?: number,
+		yMin?: number,
+		yMax?: number,
+		zMin?: number,
+		zMax?: number
+	}
+}
+
+export const Default_GraphProps : GraphProps = {
+	zoomType: Zoom3DType.Normal,
+	showAxes: true,
+	quality: 30,
+	range: {
+		xMin: -10,
+		xMax: 10,
+		yMin: -10,
+		yMax: 10,
+		zMin: -10,
+		zMax: 10
+	}
+}
+
+export function debounce(fn, delay) {
+  var timer = null;
+  return function () {
+    var context = this, args = arguments;
+    clearTimeout(timer);
+    timer = setTimeout(function () {
+      fn.apply(context, args);
+    }, delay);
+  };
+}
+
diff --git a/Frontend Angular 4/src/app/layout/plotter/graph3D/graph3D.module.ts b/Frontend Angular 4/src/app/layout/plotter/graph3D/graph3D.module.ts
index 04978608b7acb8ae9599aaecf7864c5c8bcbcf26..1df9cb3ac17e699be6577bd704445c58701a6023 100644
--- a/Frontend Angular 4/src/app/layout/plotter/graph3D/graph3D.module.ts	
+++ b/Frontend Angular 4/src/app/layout/plotter/graph3D/graph3D.module.ts	
@@ -5,12 +5,15 @@ import { NgbModule } from '@ng-bootstrap/ng-bootstrap';
 import { FormsModule } from '@angular/forms';
 import { Graph3DComponent } from './graph3D.component';
 import { AnimationControlComponent } from '../animation-control/animation-control.component';
+import { ClosePopoverOnOutsideClickDirective } from '../../../shared/utils/closePopoverDirective';
+
 
 @NgModule({
     imports: [FormsModule, RouterModule, CommonModule, NgbModule],
     declarations: [
         AnimationControlComponent, 
-        Graph3DComponent
+        Graph3DComponent,
+        ClosePopoverOnOutsideClickDirective
     ],
     entryComponents: [
         AnimationControlComponent
diff --git a/Frontend Angular 4/src/app/shared/config.ts b/Frontend Angular 4/src/app/shared/config.ts
index 85af34a7927b7193fcd816725361aa4465e248eb..970a385ea5a95fdc0c8f623e08d4d760b19996a0 100755
--- a/Frontend Angular 4/src/app/shared/config.ts	
+++ b/Frontend Angular 4/src/app/shared/config.ts	
@@ -4,12 +4,15 @@
 //export const SERVER = 'http://localhost:9090';
 //export const GHCI_URL = 'ws://localhost:9090/endpoint';
 
-export const SERVER = 'http://localhost:8080';
-export const GHCI_URL = 'ws://localhost:8080/endpoint';
+//export const SERVER = 'http://localhost:8080';
+//export const GHCI_URL = 'ws://localhost:8080/endpoint';
 
 //Configuracion dinamica pensando en servidor con ip dinamica
-//export const SERVER = window.location.protocol + '//' + window.location.host;//'http://localhost:9090';
-//export const GHCI_URL = window.location.protocol == 'http:'?  'ws://'+window.location.host+'/endpoint': 'wss://'+window.location.host+'/endpoint';
 
-//export const SERVER = 'http://ec2-52-15-74-22.us-east-2.compute.amazonaws.com:9090';
-//export const GHCI_URL = 'ws://ec2-52-15-74-22.us-east-2.compute.amazonaws.com:9090/endpoint';
\ No newline at end of file
+// export const SERVER = window.location.protocol + '//' + window.location.host;//'http://localhost:9090';
+// export const GHCI_URL = window.location.protocol == 'http:'?  'ws://'+window.location.host+'/endpoint': 'wss://'+window.location.host+'/endpoint';
+
+// Google cloud platform
+export const SERVER = 'http://35.199.110.129:9090';
+export const GHCI_URL = 'ws://35.199.110.129:9090/endpoint';
+
diff --git a/Frontend Angular 4/src/app/shared/config_BACKUP_716.ts b/Frontend Angular 4/src/app/shared/config_BACKUP_716.ts
new file mode 100644
index 0000000000000000000000000000000000000000..ed62e5eb702ba84bf84643313f102e44ad40248c
--- /dev/null
+++ b/Frontend Angular 4/src/app/shared/config_BACKUP_716.ts	
@@ -0,0 +1,28 @@
+//export const SERVER = 'https://matefun.mybluemix.net';
+//export const GHCI_URL = 'wss://matefun.mybluemix.net/endpoint';
+
+//export const SERVER = 'http://localhost:9090';
+//export const GHCI_URL = 'ws://localhost:9090/endpoint';
+
+export const SERVER = 'http://localhost:8080';
+export const GHCI_URL = 'ws://localhost:8080/endpoint';
+
+//Configuracion dinamica pensando en servidor con ip dinamica
+<<<<<<< HEAD
+//export const SERVER = window.location.protocol + '//' + window.location.host;//'http://localhost:9090';
+//export const GHCI_URL = window.location.protocol == 'http:'?  'ws://'+window.location.host+'/endpoint': 'wss://'+window.location.host+'/endpoint';
+
+//export const SERVER = 'http://ec2-52-15-74-22.us-east-2.compute.amazonaws.com:9090';
+//export const GHCI_URL = 'ws://ec2-52-15-74-22.us-east-2.compute.amazonaws.com:9090/endpoint';
+=======
+
+// export const SERVER = window.location.protocol + '//' + window.location.host;//'http://localhost:9090';
+// export const GHCI_URL = window.location.protocol == 'http:'?  'ws://'+window.location.host+'/endpoint': 'wss://'+window.location.host+'/endpoint';
+
+//export const SERVER = 'http://192.168.95.3:9090';
+//export const GHCI_URL = 'ws://192.168.95.3:9090/endpoint';
+
+export const SERVER = 'http://35.199.110.129:9090';
+export const GHCI_URL = 'ws://35.199.110.129:9090/endpoint';
+
+>>>>>>> feature/3DComponentInitialization
diff --git a/Frontend Angular 4/src/app/shared/utils/closePopoverDirective.ts b/Frontend Angular 4/src/app/shared/utils/closePopoverDirective.ts
new file mode 100644
index 0000000000000000000000000000000000000000..2faa9261792d65e5938fe733a99a583f498e44b5
--- /dev/null
+++ b/Frontend Angular 4/src/app/shared/utils/closePopoverDirective.ts	
@@ -0,0 +1,34 @@
+import { Directive, HostListener, ElementRef, ComponentRef } from '@angular/core';
+import { NgbPopover } from '@ng-bootstrap/ng-bootstrap';
+import { NgbPopoverWindow } from '@ng-bootstrap/ng-bootstrap/popover/popover';
+
+@Directive({
+  selector: '[closePopoverOnOutsideClick][ngbPopover]'
+})
+export class ClosePopoverOnOutsideClickDirective {
+
+  constructor(private elementRef: ElementRef,
+              private ngbPopover: NgbPopover) {
+
+  }
+
+  @HostListener('document:click', ['$event'])
+  private documentClicked(event: MouseEvent): void {
+
+    // Popover is open
+    if (this.ngbPopover && this.ngbPopover.isOpen()) {
+
+      // Not clicked on self element
+      if (!this.elementRef.nativeElement.contains(event.target)) {
+
+        // Hacking typescript to access private member
+        const popoverWindowRef: ComponentRef<NgbPopoverWindow> = (this.ngbPopover as any)._windowRef;
+
+        // If clicked outside popover window
+        if (!popoverWindowRef.location.nativeElement.contains(event.target)) {
+          this.ngbPopover.close();
+        }
+      }
+    }
+  }
+}
\ No newline at end of file