问:
Jackson databind working in IDE environment but not in jar
I am trying to use jackson databind using Maven. It works fine in my IDE environment (I'm using IntelliJ IDEA), but when I try to make a jar with it, it produces an error on startup and instantly crashes. Specifically, the error is this :

```<code>java.lang.NoClassDefFoundError: com/fasterxml/jackson/core/JsonFactory
</code>```

This is specific to the JAR, and I don't know why it does that at all.
What did I do wrong ?

Here is the pom file :

```<code><?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>

    <groupId>me.zam</groupId>
    <artifactId>jackson</artifactId>
    <version>1.0-SNAPSHOT</version>

    <packaging>jar</packaging>

    <dependencies>
        <dependency>
            <groupId>com.fasterxml.jackson.core</groupId>
            <artifactId>jackson-databind</artifactId>
            <version>2.2.3</version>
        </dependency>
        <dependency>
            <groupId>com.fasterxml.jackson.dataformat</groupId>
            <artifactId>jackson-dataformat-yaml</artifactId>
            <version>2.3.0</version>
        </dependency>
    </dependencies>

    <build>
        <plugins>
            <!-- Make this jar executable -->
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-jar-plugin</artifactId>
                <configuration>
                    <archive>
                        <manifest>
                            <!-- Jar file entry point -->
                            <mainClass>me.Main</mainClass>
                            <addClasspath>true</addClasspath>
                        </manifest>
                    </archive>
                </configuration>
            </plugin>
        </plugins>
    </build>

</project>
</code>```

And here is the Main object

```<code>package me;

import com.fasterxml.jackson.core.JsonFactory;
import com.fasterxml.jackson.databind.ObjectMapper;

import java.io.File;

/**
 * Created by Martin on 31/03/2017.
 */
public class Main
{
    public static void main(String[] args)
    {
        ObjectMapper mapper = new ObjectMapper(new YAMLFactory());
        try {
            User user = mapper.readValue(new File("user.yaml"), User.class);
        } catch (Exception e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
    }
}
</code>```

答:
So I just tried it in my system and was able to reproduce the issue.

To solve it you need to add one more plugin maven-shade-plugin, which is required to create the fat jar, i.e. Jar with all the required dependency.

Update pom.xml file, note here I've renamed the class which contains main method to Test and put into the default package:-

```<code> <?xml version="1.0" encoding="UTF-8"?>
    <project xmlns="http://maven.apache.org/POM/4.0.0"
             xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
             xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
        <modelVersion>4.0.0</modelVersion>

        <groupId>com.so</groupId>
        <artifactId>jackson</artifactId>
        <version>1.0-SNAPSHOT</version>

        <packaging>jar</packaging>

        <properties>
            <mainClass>Test</mainClass>
        </properties>

        <dependencies>
            <dependency>
                <groupId>com.fasterxml.jackson.core</groupId>
                <artifactId>jackson-databind</artifactId>
                <version>2.2.3</version>
            </dependency>
            <dependency>
                <groupId>com.fasterxml.jackson.dataformat</groupId>
                <artifactId>jackson-dataformat-yaml</artifactId>
                <version>2.3.0</version>
            </dependency>
        </dependencies>

        <build>
            <plugins>
                <plugin>
                    <artifactId>maven-shade-plugin</artifactId>
                    <version>2.4.1</version>
                    <configuration>
                        <createDependencyReducedPom>true</createDependencyReducedPom>
                        <transformers>
                            <transformer implementation="org.apache.maven.plugins.shade.resource.ServicesResourceTransformer"/>
                            <transformer implementation="org.apache.maven.plugins.shade.resource.ManifestResourceTransformer">
                                <mainClass>${mainClass}</mainClass>
                            </transformer>
                        </transformers>
                        <!-- exclude signed Manifests -->
                        <filters>
                            <filter>
                                <artifact>*:*</artifact>
                                <excludes>
                                    <exclude>META-INF/*.SF</exclude>
                                    <exclude>META-INF/*.DSA</exclude>
                                    <exclude>META-INF/*.RSA</exclude>
                                </excludes>
                            </filter>
                        </filters>
                    </configuration>
                    <executions>
                        <execution>
                            <phase>package</phase>
                            <goals>
                                <goal>shade</goal>
                            </goals>
                        </execution>
                    </executions>
                </plugin>
                <!-- Make this jar executable -->
                <plugin>
                    <groupId>org.apache.maven.plugins</groupId>
                    <artifactId>maven-jar-plugin</artifactId>
                    <configuration>
                        <archive>
                            <manifest>
                                <!-- Jar file entry point -->
                                <mainClass>Test</mainClass>
                                <addClasspath>true</addClasspath>
                            </manifest>
                        </archive>
                    </configuration>
                </plugin>
            </plugins>
        </build>

    </project>
</code>```

Once done, I ran the code by running first mvn clean package command, which creates the fat jar and then run the code by java -cp target/jackson-1.0-SNAPSHOT.jar Test command.

Let me know if you face any issue running the code.

Body:
I am trying to use jackson databind using Maven. It works fine in my IDE environment (I'm using IntelliJ IDEA), but when I try to make a jar with it, it produces an error on startup and instantly crashes. Specifically, the error is this :

java.lang.NoClassDefFoundError: com/fasterxml/jackson/core/JsonFactory

This is specific to the JAR, and I don't know why it does that at all.
What did I do wrong ?

Here is the pom file :

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>

    <groupId>me.zam</groupId>
    <artifactId>jackson</artifactId>
    <version>1.0-SNAPSHOT</version>

    <packaging>jar</packaging>

    <dependencies>
        <dependency>
            <groupId>com.fasterxml.jackson.core</groupId>
            <artifactId>jackson-databind</artifactId>
            <version>2.2.3</version>
        </dependency>
        <dependency>
            <groupId>com.fasterxml.jackson.dataformat</groupId>
            <artifactId>jackson-dataformat-yaml</artifactId>
            <version>2.3.0</version>
        </dependency>
    </dependencies>

    <build>
        <plugins>

            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-jar-plugin</artifactId>
                <configuration>
                    <archive>
                        <manifest>

                            <mainClass>me.Main</mainClass>
                            <addClasspath>true</addClasspath>
                        </manifest>
                    </archive>
                </configuration>
            </plugin>
        </plugins>
    </build>

</project>

And here is the Main object

package me;

import com.fasterxml.jackson.core.JsonFactory;
import com.fasterxml.jackson.databind.ObjectMapper;

import java.io.File;

/**
 * Created by Martin on 31/03/2017.
 */
public class Main
{
    public static void main(String[] args)
    {
        ObjectMapper mapper = new ObjectMapper(new YAMLFactory());
        try {
            User user = mapper.readValue(new File("user.yaml"), User.class);
        } catch (Exception e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
    }
}

Body:
So I just tried it in my system and was able to reproduce the issue.

To solve it you need to add one more plugin maven-shade-plugin, which is required to create the fat jar, i.e. Jar with all the required dependency.

Update pom.xml file, note here I've renamed the class which contains main method to Test and put into the default package:-

 <?xml version="1.0" encoding="UTF-8"?>
    <project xmlns="http://maven.apache.org/POM/4.0.0"
             xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
             xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
        <modelVersion>4.0.0</modelVersion>

        <groupId>com.so</groupId>
        <artifactId>jackson</artifactId>
        <version>1.0-SNAPSHOT</version>

        <packaging>jar</packaging>

        <properties>
            <mainClass>Test</mainClass>
        </properties>

        <dependencies>
            <dependency>
                <groupId>com.fasterxml.jackson.core</groupId>
                <artifactId>jackson-databind</artifactId>
                <version>2.2.3</version>
            </dependency>
            <dependency>
                <groupId>com.fasterxml.jackson.dataformat</groupId>
                <artifactId>jackson-dataformat-yaml</artifactId>
                <version>2.3.0</version>
            </dependency>
        </dependencies>

        <build>
            <plugins>
                <plugin>
                    <artifactId>maven-shade-plugin</artifactId>
                    <version>2.4.1</version>
                    <configuration>
                        <createDependencyReducedPom>true</createDependencyReducedPom>
                        <transformers>
                            <transformer implementation="org.apache.maven.plugins.shade.resource.ServicesResourceTransformer"/>
                            <transformer implementation="org.apache.maven.plugins.shade.resource.ManifestResourceTransformer">
                                <mainClass>${mainClass}</mainClass>
                            </transformer>
                        </transformers>
                        <!-- exclude signed Manifests -->
                        <filters>
                            <filter>
                                <artifact>*:*</artifact>
                                <excludes>
                                    <exclude>META-INF/*.SF</exclude>
                                    <exclude>META-INF/*.DSA</exclude>
                                    <exclude>META-INF/*.RSA</exclude>
                                </excludes>
                            </filter>
                        </filters>
                    </configuration>
                    <executions>
                        <execution>
                            <phase>package</phase>
                            <goals>
                                <goal>shade</goal>
                            </goals>
                        </execution>
                    </executions>
                </plugin>
                <!-- Make this jar executable -->
                <plugin>
                    <groupId>org.apache.maven.plugins</groupId>
                    <artifactId>maven-jar-plugin</artifactId>
                    <configuration>
                        <archive>
                            <manifest>
                                <!-- Jar file entry point -->
                                <mainClass>Test</mainClass>
                                <addClasspath>true</addClasspath>
                            </manifest>
                        </archive>
                    </configuration>
                </plugin>
            </plugins>
        </build>

    </project>

Once done, I ran the code by running first mvn clean package command, which creates the fat jar and then run the code by java -cp target/jackson-1.0-SNAPSHOT.jar Test command.

Let me know if you face any issue running the code.

ContentLicense: CC BY-SA 4.0


来源: stackexchange

问:
Is it possible to Migrate from RHEL 5.11 to RHEL 7.1?
I want to upgrade the current RHEL version for one of my production system. The current version is RHEL 5.11. Is it possible to install and migrate old setting to RHEL 7.1 without any challenges?</p>

答:
It is possible, though not without "challenges".

See How do I migrate from RHEL5 to RHEL7? A direct upgrade path is not supported by Red Hat, but the linked article contains detailed information about all aspects of the process.

See also Does Red Hat support upgrades between major versions of Red Hat Enterprise Linux? for general info about upgrades between major versions of RHEL.

ContentLicense: CC BY-SA 3.0


问:
How to extend method run in TimerTask . Must accept string parameter
I have this code

```<code>private void startActionPerformed(java.awt.event.ActionEvent evt) {
    this.start.setBackground(Color.green);
    this.stop.setBackground(Color.lightGray);
    if (!stopped) {
        timer.cancel();
    }
    stopped = false;
    stato.setText("Avviato");
    timer = new Timer();
    if(giacRitardo>0)
        timer.schedule(S.run("argiacenze"), giacRitardo, giacRitardo);//parti dopo x secondi e itera ogni x secondi
    if(cliRitardo>0)
        timer.schedule(S.run("arclienti"), cliRitardo, cliRitardo);//parti dopo x secondi e itera ogni x secondi
</code>```

// some other code

and

```<code>class TaskSchedulato extends TimerTask {

    @Override
    public void run() {
        redirectSystemStreams();
        DateFormat sdf = new SimpleDateFormat("yyyy/MM/dd HH:mm:ss");
        URL sito = null;
        try {
            sito = new URL(sUrl + "?aggiornamento=arlingue");
        } catch (MalformedURLException ex) {
            System.out.println("Indirizzo del sito mal formato o inesistente");
        }
        URLConnection yc = null;
        try {
            yc = sito.openConnection();
        } catch (IOException ex) {
            System.out.println("Errore di connessione _ ");
        }
        BufferedReader in = null;
        try {
            in = new BufferedReader(
                    new InputStreamReader(
                            yc.getInputStream()));
        } catch (IOException ex) {
            Logger.getLogger(TaskSchedulato.class.getName()).log(Level.SEVERE, null, ex);
        }
        String inputLine;
        try {
            while ((inputLine = in.readLine()) != null) {
                System.out.println(inputLine);
            }
        } catch (IOException ex) {
            Logger.getLogger(TaskSchedulato.class.getName()).log(Level.SEVERE, null, ex);
            dataErrore = new Date();
            System.out.println(sdf.format(dataErrore));
            System.out.println("Errore di connessione: " + dataErrore);
        }
        try {
            in.close();
        } catch (IOException ex) {
            Logger.getLogger(TaskSchedulato.class.getName()).log(Level.SEVERE, null, ex);
        }

    }
}
</code>```

and

```<code>TaskSchedulato S = new TaskSchedulato();
</code>```

I need to extend the method run above, so that i can pass a string parameter to it.
How can a do it.
I'm almost a newbye in java. So, please forgive me for the inexperience.

Actually I receive the error:
no suitable method found for run(String)
  method TimerTask.run() is not applicable
(actual and formal argument lists differ in length)
method MainForm.TaskSchedulato.run() is not applicable
(actual and formal argument lists differ in length)

Thank you in advance

答:
@domdom,
signature of timer.schedule is
    schedule(TimerTask task,long delay,long period)

I already used it in my working version of the program

```<code>private void startActionPerformed(java.awt.event.ActionEvent evt) {
    this.start.setBackground(Color.green);
    this.stop.setBackground(Color.lightGray);
    if (!stopped) {
        timer.cancel();
    }
    stopped = false;
    stato.setText("Avviato");
    timer = new Timer();
    if(giacRitardo>0)
        timer.schedule(new TaskGiacenze(), giacRitardo, giacRitardo);
    if(cliRitardo>0)
        timer.schedule(new TaskClienti(), cliRitardo, cliRitardo);
    if(artRitardo>0)
        timer.schedule(new TaskArticoli(), artRitardo, artRitardo
    //..........
</code>```

and

```<code>class TaskGiacenze extends TimerTask {

    @Override
    public void run() {
        redirectSystemStreams();
        DateFormat sdf = new SimpleDateFormat("yyyy/MM/dd HH:mm:ss");
        URL sito = null;
        try {
            sito = new URL(sUrl + "?aggiornamento=argiacenze");
        } catch (MalformedURLException ex) {
            System.out.println("Indirizzo del sito mal formato o inesistente");
        }
        URLConnection yc = null;
        try {
            yc = sito.openConnection();
        } catch (IOException ex) {
            System.out.println("Errore di connessione _ ");
        }
        BufferedReader in = null;
        try {
            in = new BufferedReader(
                    new InputStreamReader(
                            yc.getInputStream()));
        } catch (IOException ex) {
            Logger.getLogger(TaskGiacenze.class.getName()).log(Level.SEVERE, null, ex);
        }
        String inputLine;
        try {
            while ((inputLine = in.readLine()) != null) {
                System.out.println(inputLine);
            }
        } catch (IOException ex) {
            Logger.getLogger(TaskGiacenze.class.getName()).log(Level.SEVERE, null, ex);
            dataErrore = new Date();
            System.out.println(sdf.format(dataErrore));
            System.out.println("Errore di connessione: " + dataErrore);
        }
        try {
            in.close();
        } catch (IOException ex) {
            Logger.getLogger(TaskGiacenze.class.getName()).log(Level.SEVERE, null, ex);
        }
    }
}
</code>```

but I had to create a class for each kind (one class for giacenze, another class for articoli etc.. etc...) instead of calling it as parameter.

Body:
I have this code

private void startActionPerformed(java.awt.event.ActionEvent evt) {
    this.start.setBackground(Color.green);
    this.stop.setBackground(Color.lightGray);
    if (!stopped) {
        timer.cancel();
    }
    stopped = false;
    stato.setText("Avviato");
    timer = new Timer();
    if(giacRitardo>0)
        timer.schedule(S.run("argiacenze"), giacRitardo, giacRitardo);//parti dopo x secondi e itera ogni x secondi
    if(cliRitardo>0)
        timer.schedule(S.run("arclienti"), cliRitardo, cliRitardo);//parti dopo x secondi e itera ogni x secondi

// some other code

and

class TaskSchedulato extends TimerTask {

    @Override
    public void run() {
        redirectSystemStreams();
        DateFormat sdf = new SimpleDateFormat("yyyy/MM/dd HH:mm:ss");
        URL sito = null;
        try {
            sito = new URL(sUrl + "?aggiornamento=arlingue");
        } catch (MalformedURLException ex) {
            System.out.println("Indirizzo del sito mal formato o inesistente");
        }
        URLConnection yc = null;
        try {
            yc = sito.openConnection();
        } catch (IOException ex) {
            System.out.println("Errore di connessione _ ");
        }
        BufferedReader in = null;
        try {
            in = new BufferedReader(
                    new InputStreamReader(
                            yc.getInputStream()));
        } catch (IOException ex) {
            Logger.getLogger(TaskSchedulato.class.getName()).log(Level.SEVERE, null, ex);
        }
        String inputLine;
        try {
            while ((inputLine = in.readLine()) != null) {
                System.out.println(inputLine);
            }
        } catch (IOException ex) {
            Logger.getLogger(TaskSchedulato.class.getName()).log(Level.SEVERE, null, ex);
            dataErrore = new Date();
            System.out.println(sdf.format(dataErrore));
            System.out.println("Errore di connessione: " + dataErrore);
        }
        try {
            in.close();
        } catch (IOException ex) {
            Logger.getLogger(TaskSchedulato.class.getName()).log(Level.SEVERE, null, ex);
        }

    }
}

and

TaskSchedulato S = new TaskSchedulato();

I need to extend the method run above, so that i can pass a string parameter to it.
How can a do it.
I'm almost a newbye in java. So, please forgive me for the inexperience.

Actually I receive the error:
no suitable method found for run(String)
  method TimerTask.run() is not applicable
(actual and formal argument lists differ in length)
method MainForm.TaskSchedulato.run() is not applicable
(actual and formal argument lists differ in length)

Thank you in advance

Body:
@domdom,
signature of timer.schedule is
    schedule(TimerTask task,long delay,long period)

I already used it in my working version of the program

private void startActionPerformed(java.awt.event.ActionEvent evt) {
    this.start.setBackground(Color.green);
    this.stop.setBackground(Color.lightGray);
    if (!stopped) {
        timer.cancel();
    }
    stopped = false;
    stato.setText("Avviato");
    timer = new Timer();
    if(giacRitardo>0)
        timer.schedule(new TaskGiacenze(), giacRitardo, giacRitardo);
    if(cliRitardo>0)
        timer.schedule(new TaskClienti(), cliRitardo, cliRitardo);
    if(artRitardo>0)
        timer.schedule(new TaskArticoli(), artRitardo, artRitardo
    //..........

and

class TaskGiacenze extends TimerTask {

    @Override
    public void run() {
        redirectSystemStreams();
        DateFormat sdf = new SimpleDateFormat("yyyy/MM/dd HH:mm:ss");
        URL sito = null;
        try {
            sito = new URL(sUrl + "?aggiornamento=argiacenze");
        } catch (MalformedURLException ex) {
            System.out.println("Indirizzo del sito mal formato o inesistente");
        }
        URLConnection yc = null;
        try {
            yc = sito.openConnection();
        } catch (IOException ex) {
            System.out.println("Errore di connessione _ ");
        }
        BufferedReader in = null;
        try {
            in = new BufferedReader(
                    new InputStreamReader(
                            yc.getInputStream()));
        } catch (IOException ex) {
            Logger.getLogger(TaskGiacenze.class.getName()).log(Level.SEVERE, null, ex);
        }
        String inputLine;
        try {
            while ((inputLine = in.readLine()) != null) {
                System.out.println(inputLine);
            }
        } catch (IOException ex) {
            Logger.getLogger(TaskGiacenze.class.getName()).log(Level.SEVERE, null, ex);
            dataErrore = new Date();
            System.out.println(sdf.format(dataErrore));
            System.out.println("Errore di connessione: " + dataErrore);
        }
        try {
            in.close();
        } catch (IOException ex) {
            Logger.getLogger(TaskGiacenze.class.getName()).log(Level.SEVERE, null, ex);
        }
    }
}

but I had to create a class for each kind (one class for giacenze, another class for articoli etc.. etc...) instead of calling it as parameter.


问:
Persisting Wordpress Custom Taxonomy Tag In Permalink
In wordpress I need to prefix the permalink with a custom taxonomy tag lets say %writer% and maintain the standard category structure after that.

For e.g

/steve-brookes/novels/thrillers/

Where novels/thrillers is the standard hierarchical category structure. So i dont need to recreate the category structure for each writer.

I can persist this tag no problem in a session variable grabbing get_query_var('writer'); and modify the url to suit using this to persist the writer tag. This maintains the tag when navigating through the categories. Until you go back and change the writer.

I thought I had achieved this however prefixing the permalink seems to create issues with pages throwing 404 errors, as the pages dont have a category prefix and WP thinks the page name is a writter.

I can append the tag to the end of the permalink and there is no problem:

/%category%/%postname%/%writer%/
/novels/thrillers/steve-brookes/

all works as expected including pages.

But doing this:

/%writer%/%postname%/%category%/
/steve-brookes/thrillers/novels/

Causes pages to throw 404 errors.

I know there are plenty of posts on this on SO and the web but doesnt seem to cover this.

Any help appreciated.

答:
Working with the same problem right now. Trying to add my taxonomy slug at the beginning of my permalinks.
It seems that when you make first permalink section dynamic, it creates a conflict with the pages structure, which consists only from one dynamic section - %pagename%.
I haven't succeeded with rewrite rules to bypass it.
The only workaround I found yet is to make pages permastructure more specific:</p>

```<code>global $wp_rewrite;
$wp_rewrite->page_structure = 'page/%pagename%';
</code>```

Body:
Working with the same problem right now. Trying to add my taxonomy slug at the beginning of my permalinks.
It seems that when you make first permalink section dynamic, it creates a conflict with the pages structure, which consists only from one dynamic section - %pagename%.
I haven't succeeded with rewrite rules to bypass it.
The only workaround I found yet is to make pages permastructure more specific:

global $wp_rewrite;
$wp_rewrite->page_structure = 'page/%pagename%';


问:
error C2143: syntax error : missing ';' before '*'
I'm not new to C++ but I am used to running a g++ compiler vs Microsoft's VS C++. I understand what this error should mean. It should mean that I'm missing a ';' on the line before or in the class Polygon. I can't seem to find anything wrong. g++ compiles the code without error. It seems like the Polygon Class isn't being loaded. Can anyone please show me what I'm missing please.I have the Application.cpp, Polygon.h, and Polygon.cpp below.

Application.cpp throwing errors but if I can fix the first others will follow:

application.cpp(121) : error C2143: syntax error : missing ';' before '*'

application.cpp(121) : error C4430: missing type specifier - int assumed. Note: C++ does not support default-int

application.cpp(121) : error C2365: 'Polygon' : redefinition; previous definition was 'function'
c:\program files\microsoft sdks\windows\v6.0a\include\wingdi.h(4203) : see declaration of 'Polygon'

```#include <sstream>
#include <numeric>
#include <math.h>
#include "Polygon.h"

#define PI 3.14159265

//use standard namespace
using namespace std;

 /**************************** Window Variables ****************************/

double _window_height   = 500;
double _window_width   = 500;
double _window_position_x  = 0;
double _window_position_y  = 0;

string _window_title ("Assignment 5");

/**************************** Object Variables ****************************/

int _my_shape     = 0;
GLint _object_shine    = 40;
double _object_y_rotation  = 0;

GLfloat ambient_reflection[3] = {1.0, 1.0, 1.0};
GLfloat diffuse_reflection[3] = {1.0, 1.0, 1.0};
GLfloat specular_reflection[3] = {1.0, 1.0, 1.0};
GLfloat emissive_color[3]  = {0.0, 0.0, 0.0};
int specular_exponent   = 0;

/*************************** Lighting Variables ***************************/

//Global Light settings

GLfloat _global_ambient_light[] = {0.5, 0.5, 0.5, 1.0};
GLfloat _global_diffuse_light[] = {0.7, 0.7, 0.7, 1.0};

int rotation_int     = 0;
int rotation_angle    = 90;
int _CAMERA_DISTANCE   = 2;

//Light 0 Settings

GLfloat _z_axis_rotations[8][4] = {{(_CAMERA_DISTANCE*cos((90)*PI/180)), (_CAMERA_DISTANCE*sin((90)*PI/180)), 0.0, 1.0},
         {(_CAMERA_DISTANCE*cos((45)*PI/180)), (_CAMERA_DISTANCE*sin((45)*PI/180)), 0.0, 1.0},
         {(_CAMERA_DISTANCE*cos((0)*PI/180)), (_CAMERA_DISTANCE*sin((0)*PI/180)), 0.0, 1.0},
         {(_CAMERA_DISTANCE*cos((315)*PI/180)), (_CAMERA_DISTANCE*sin((315)*PI/180)), 0.0, 1.0},
         {(_CAMERA_DISTANCE*cos((270)*PI/180)), (_CAMERA_DISTANCE*sin((270)*PI/180)), 0.0, 1.0},
         {(_CAMERA_DISTANCE*cos((225)*PI/180)), (_CAMERA_DISTANCE*sin((225)*PI/180)), 0.0, 1.0},
         {(_CAMERA_DISTANCE*cos((180)*PI/180)), (_CAMERA_DISTANCE*sin((180)*PI/180)), 0.0, 1.0},
         {(_CAMERA_DISTANCE*cos((135)*PI/180)), (_CAMERA_DISTANCE*sin((135)*PI/180)), 0.0, 1.0}};

GLfloat _ambient_0_light[]   = {0.3f, 0.3f, 0.3f, 1.0f};
GLfloat _diffuse_0_light[]   = {0.6f, 0.6f, 0.6f, 1.0f};
GLfloat _specular_0_light[]  = {0.6f, 0.6f, 0.6f, 1.0f};
GLfloat _specular_0_property[]  = {0.6f, 0.6f, 0.6f, 1.0f};

//Light 1 Settings

// Green Spotlight with narrow angle
GLfloat _light_1_position[]  = {2.0, 0.0, -0.5, 1.0};
GLfloat _diffuse_1_light[]   = {0.2, 0.4, 0.9, 1.0};
GLfloat _spot_1_direction[]  = {-0.3, -2.0, -0.3};

//Light 2 Settings

// Red Spotlight with wide angle
GLfloat _light_2_position[]  = {0.3, -0.5, 4.0, 1.0};
GLfloat _diffuse_2_light[]   = {1.0, 0.2, 0.6, 1.0};
GLfloat _spot_2_direction[]  = {0.3, -0.5, -2.0};

GLfloat _cutoff     = 90.0;

GLfloat _AMBIENT_CONSTANT  = 0.1;
GLfloat _DIFFUSE_CONSTANT  = 0.1;
GLfloat _EMISSION_CONSTANT  = 0.05;
GLfloat _SPECULAR_CONSTANT  = 0.1;
int _SPECULAR_EXPONENT_CONSTANT = 1;
int _CUTOFF_CONSTANT   = 1;

/*************************** Shading Variables ***************************/

bool _shade_model_smooth  = true;

/**************************** File Variables *****************************/

//Error String printed if the file is not found
string _FILE_OPEN_ERROR = "Error: File could not be found or opened.";

//Error String printed if the file is not formed correctly
string _CHOICE_INVALID_ERROR = "Error: The choice you made was not one that is defined.";

/** for file reading **/
//The Array for holding all the Polygons
Polygon** _Polygons;
//the current size of the Polygon Array
int _polygons_max = 10;
//the current element for processing in the Polygon Array
int _polygons_current = 0;

/* ReadFromFile
 *
 * This method will ask a filename from the user and either return to
 * the user a file not found error or will read in from the file the
 * coordinates and place them in the coordinate array, while also setting
 * the number of lines that make up a shape.
 */
void ReadFromFile(){

 ifstream input; //  input file stream
 string filename = ""; //  used to store filename
 string line = ""; // temporary storage for reading lines at a time

 // cout << "Type a filename and press Enter: ";
 // cin >> filename;
 //cout << "Type a filename and press Enter: dodecahedron.dat" << endl;
 filename = "dodec.dat";//"dodecahedron.dat"; //should be 36 polygons

 input.open (filename.c_str(), ifstream::in);//try to open the file
 if(input.is_open()){ //check if file is open

  _Polygons = new Polygon*[_polygons_max];

  double _light_settings[12] = {0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0};
  int SH = 0;
  double _normals[3] = {0.0, 0.0, 0.0};

  int _coordinate_count = 0;
  int _coordinate_max = 4;
  double** _coordinates = new double*[_coordinate_max];

  while (input.good()){ //not eof or failbit

   /* Ensure space is available */
   if(_polygons_current >= _polygons_max){

    _polygons_max = _polygons_max * 2; //double max size
    Polygon** temp = new Polygon*[_polygons_max]; //create bigger array

    for (int j = 0; j <_polygons_current; j++) {
     temp[j] = _Polygons[j]; // copy values to new array.
    }

    delete [] _Polygons; //free old array memory
    _Polygons = temp; //transfer polygons
   }

   getline(input, line); //get the line from input

   string::size_type _last_pos = line.find_first_not_of(" ", 0);
   string::size_type _pos = line.find_first_of(" ", _last_pos);

   if((line.substr(_last_pos, _pos - _last_pos)).c_str()[0] == '#'){ //comment
    //do nothing for this line
   }else if((line.substr(_last_pos, _pos - _last_pos)).c_str()[0] == 'J' ||
     (line.substr(_last_pos, _pos - _last_pos)).c_str()[0] == 'j'){ //polygon start

    if(_coordinate_count != 0){

     //cout << "Polygon #" << _polygons_current << endl;

     _Polygons[_polygons_current] = new Polygon(_coordinate_count, _coordinates);
     _Polygons[_polygons_current]->setAmbientReflection(_light_settings[0], _light_settings[1], _light_settings[2]);
     _Polygons[_polygons_current]->setDiffuseReflection(_light_settings[3], _light_settings[4], _light_settings[5]);
     _Polygons[_polygons_current]->setSpecularReflection(_light_settings[6], _light_settings[7], _light_settings[8]);
     _Polygons[_polygons_current]->setEmissiveColor(_light_settings[9], _light_settings[10], _light_settings[11]);
     _Polygons[_polygons_current]->setSurfaceNormals(_normals[0], _normals[1], _normals[2]);
     _Polygons[_polygons_current]->setSpecularExponent(SH);

     for(int i=0; i<_coordinate_count; i++){
      delete _coordinates[i];
     }

     _coordinate_count = 0;
     _polygons_current++;
    }

    if(line.find_first_not_of(" ", _pos) != string::npos){

     for(int i=0; i<12; i++){
      _last_pos = line.find_first_not_of(" ", _pos);
      _pos = line.find_first_of(" ", _last_pos);
      _light_settings[i] = atof(line.substr(_last_pos, _pos - _last_pos).c_str());
     }

     _last_pos = line.find_first_not_of(" ", _pos);
     _pos = line.find_first_of(" ", _last_pos);
     SH = atoi(line.substr(_last_pos, _pos - _last_pos).c_str());

     for(int i=0; i<3; i++){
      _last_pos = line.find_first_not_of(" ", _pos);
      _pos = line.find_first_of(" ", _last_pos);
      _normals[i] = atof(line.substr(_last_pos, _pos - _last_pos).c_str());
     }
    }

   }else{

    /* Ensure space is available */
    if(_coordinate_count >= _coordinate_max){

     _coordinate_max = _coordinate_max * 2; //double max size
     double** temp = new double*[_coordinate_max]; //create bigger array

     for (int i = 0; i < _coordinate_count; i++) {
      temp[i] = new double[3];
      temp[i][0] = _coordinates[i][0]; // copy values to new array.
      temp[i][1] = _coordinates[i][1];
      temp[i][2] = _coordinates[i][3];
     }

     delete [] _coordinates; //free old array memory
     _coordinates = temp; //transfer polygons
    }

    _coordinates[_coordinate_count] = new double[3];

    for(int i=0; i<3; i++){
     _coordinates[_coordinate_count][i] = atof(line.substr(_last_pos, _pos - _last_pos).c_str());
     _last_pos = line.find_first_not_of(" ", _pos);
     _pos = line.find_first_of(" ", _last_pos);
    }
    _coordinate_count++;
   }
  }

  input.close();

 }else{

  //if the file could not be opened output to the screen the error
  cout << _FILE_OPEN_ERROR;
  exit(0);
 }
}

/* InitializeWindow
 *
 * Initializes the GLUT Library settings and creates a window for the
 * program to be displayed in.
 *
 */
void InitializeWindow(int argc, char** argv){

 glutInit(&argc,argv); /* Initialize GLUT */
 glutInitDisplayMode( GLUT_RGB | GLUT_SINGLE | GLUT_DEPTH );/* Specify display mode */
 glutInitWindowSize(_window_width, _window_height); /* Set window size */
 glutInitWindowPosition(_window_position_x, _window_position_y); /* Set window position */
 glutCreateWindow(_window_title.c_str()); /* Create Window */
}

/* InitializeEnvironment
 *
 * Initializes the Glut environment in which the drawing is to be done.
 */
void InitializeEnvironment(){

 glClearColor (0.0, 0.0, 0.0, 0.0);
 glMatrixMode(GL_MODELVIEW);
 glLoadIdentity();

 glLightModelfv(GL_LIGHT_MODEL_AMBIENT, _global_ambient_light);
 glMaterialfv(GL_FRONT, GL_AMBIENT_AND_DIFFUSE, _global_diffuse_light);

 glLoadIdentity();
 glLightfv(GL_LIGHT0, GL_POSITION, _z_axis_rotations[0]);
 glLightfv(GL_LIGHT0, GL_SPECULAR, _specular_0_light);
 glLightf(GL_LIGHT0, GL_SPOT_CUTOFF, _cutoff);
 glLightf(GL_LIGHT0, GL_SPOT_EXPONENT, 0);

 glLoadIdentity();
 glLightfv(GL_LIGHT1, GL_POSITION, _light_1_position);
 glLightfv(GL_LIGHT1, GL_DIFFUSE, _diffuse_1_light);
 //
 // glLoadIdentity();
 // glLightfv(GL_LIGHT2, GL_POSITION, light3_position);
 // glLightfv(GL_LIGHT2, GL_DIFFUSE, light3_diffuse_light);

 glEnable(GL_LIGHTING);
 glEnable(GL_DEPTH_TEST);

 glEnable(GL_LIGHT0);
 glEnable(GL_LIGHT1);

 if(_my_shape == 1){
  glFrontFace(GL_CW);
 }else{
  glFrontFace(GL_CCW);
 }

 glEnable(GL_CULL_FACE);

}

// In the main method we registered this method as the callback function for
// Keyboard input.  Anytime a key is pressed the ascii value of the key and
// the x and y positions of the mouse cursor within the window are passed to
// this function.
void Keyboard(unsigned char key, int x, int y) {

 switch (key) {
 case '1':
  glEnable(GL_LIGHT0);
  break;
 case '2':
  glEnable(GL_LIGHT1);
  break;
 case '+': /* Increase the cutoff angle of the positional light. */
  if(_cutoff == 90){
   _cutoff = 180;
  }else if((_cutoff-_CUTOFF_CONSTANT) > 180){
   _cutoff = 180;
  }else{
   _cutoff += _CUTOFF_CONSTANT;
  }
  glLightf(GL_LIGHT0, GL_SPOT_CUTOFF, _cutoff);
  break;
 case '-': /* Decrease the cutoff angle of the positional light. */
  if(_cutoff == 180){
   _cutoff = 90;
  }else if((_cutoff-_CUTOFF_CONSTANT) < 0){
   _cutoff = 0;
  }else{
   _cutoff -= _CUTOFF_CONSTANT;
  }
  glLightf(GL_LIGHT0, GL_SPOT_CUTOFF, _cutoff);
  break;
 case '0': /* Turn off the directional and positional light. */
  glDisable(GL_LIGHT0);
  glDisable(GL_LIGHT1);
  break;
 case 'a': /* Decrease the ambient light. */
  if(_global_ambient_light[0]>0){
   _global_ambient_light[0] = _global_ambient_light[1] = _global_ambient_light[2] -= _AMBIENT_CONSTANT;
   glLightModelfv(GL_LIGHT_MODEL_AMBIENT, _global_ambient_light);
  }
  break;
 case 'A': /* Increase the ambient light. */
  if(_global_ambient_light[0]<1){
   _global_ambient_light[0] = _global_ambient_light[1] = _global_ambient_light[2] += _AMBIENT_CONSTANT;
   glLightModelfv(GL_LIGHT_MODEL_AMBIENT, _global_ambient_light);
  }
  break;
 case 'd': /* Decrease the diffuse light. */
  if(_global_diffuse_light[0]>0){
   _global_diffuse_light[0] = _global_diffuse_light[1] = _global_diffuse_light[2] -= _DIFFUSE_CONSTANT;
   glMaterialfv(GL_FRONT, GL_AMBIENT_AND_DIFFUSE, _global_diffuse_light);
  }
  break;
 case 'D': /* Increase the diffuse light. */
  if(_global_diffuse_light[0]<1){
   _global_diffuse_light[0] = _global_diffuse_light[1] = _global_diffuse_light[2] += _DIFFUSE_CONSTANT;
   glMaterialfv(GL_FRONT, GL_AMBIENT_AND_DIFFUSE, _global_diffuse_light);
  }
  break;
 case 's': /* Decrease the specular component of the positional light. */
  if(_my_shape != 1){
   for(int i=0; i<3; i++){
    if((specular_reflection[i]-_SPECULAR_CONSTANT) < -1.0){
     specular_reflection[i] = -1.0;
    }else{
     specular_reflection[i] -= _SPECULAR_CONSTANT;
    }
   }
  }else{
   for(int i=0; i < _polygons_current; i++){ //Over all Polygons

    double* sr = _Polygons[i]->getSpecularReflection();

    for(int j=0; j<3; j++){
     if((sr[j]-_SPECULAR_CONSTANT) < -1.0){
      sr[j] = -1.0;
     }else{
      sr[j] -= _SPECULAR_CONSTANT;
     }
    }
   }
  }
  break;
 case 'S': /* Increase the specular component of the positional light. */
  if(_my_shape != 1){
   for(int i=0; i<3; i++){
    if((specular_reflection[i]+_SPECULAR_CONSTANT) > 1.0){
     specular_reflection[i] = 1.0;
    }else{
     specular_reflection[i] += _SPECULAR_CONSTANT;
    }
   }
  }else{
   for(int i=0; i < _polygons_current; i++){ //Over all Polygons

    double* sr = _Polygons[i]->getSpecularReflection();

    for(int j=0; j<3; j++){
     if((sr[j]+_SPECULAR_CONSTANT) > 1.0){
      sr[j] = 1.0;
     }else{
      sr[j] += _SPECULAR_CONSTANT;
     }
    }
   }
  }
  break;
 case 'h': /* Decrease the shininess of the object. */
  if(_my_shape != 1){
   if((specular_exponent-_SPECULAR_EXPONENT_CONSTANT) < 0){
    specular_exponent = 0;
   }else{
    specular_exponent-=_SPECULAR_EXPONENT_CONSTANT;
   }
  }else{
   for(int i=0; i < _polygons_current; i++){ //Over all Polygons

    int sh = _Polygons[i]->getSpecularExponent();

    if((sh-_SPECULAR_EXPONENT_CONSTANT) < 0){
     _Polygons[i]->setSpecularExponent(0);
    }else{
     _Polygons[i]->setSpecularExponent(sh-_SPECULAR_EXPONENT_CONSTANT);
    }
   }
  }
  break;
 case 'H': /* Increase the shininess of the object. */
  if(_my_shape != 1){
   if((specular_exponent+_SPECULAR_EXPONENT_CONSTANT) > 128){
    specular_exponent = 128;
   }else{
    specular_exponent+=_SPECULAR_EXPONENT_CONSTANT;
   }
  }else{
   for(int i=0; i < _polygons_current; i++){ //Over all Polygons

    int sh = _Polygons[i]->getSpecularExponent();

    if((sh+_SPECULAR_EXPONENT_CONSTANT) > 128){
     _Polygons[i]->setSpecularExponent(128);
    }else{
     _Polygons[i]->setSpecularExponent(sh+_SPECULAR_EXPONENT_CONSTANT);
    }
   }
  }
  break;
 case 'e': /* Decrease the emissive light of the object. */
  if(_my_shape != 1){
   if((emissive_color[0]-_EMISSION_CONSTANT) < 0){
    emissive_color[0] = 0;
   }else{
    emissive_color[0] -= _EMISSION_CONSTANT;
   }

   if((emissive_color[1]-_EMISSION_CONSTANT) < 0){
    emissive_color[1] = 0;
   }else{
    emissive_color[1] -= _EMISSION_CONSTANT;
   }

   if((emissive_color[2]-_EMISSION_CONSTANT) < 0){
    emissive_color[2] = 0;
   }else{
    emissive_color[2] -= _EMISSION_CONSTANT;
   }
  }else{
   for(int i=0; i < _polygons_current; i++){ //Over all Polygons

    double* ep = _Polygons[i]->getEmissiveColor();

    if((ep[0]-_EMISSION_CONSTANT) < 0){
     ep[0] = 0;
    }else{
     ep[0] -= _EMISSION_CONSTANT;
    }

    if((ep[1]-_EMISSION_CONSTANT) < 0){
     ep[1] = 0;
    }else{
     ep[1] -= _EMISSION_CONSTANT;
    }

    if((ep[2]-_EMISSION_CONSTANT) < 0){
     ep[2] = 0;
    }else{
     ep[2] -= _EMISSION_CONSTANT;
    }
   }
  }
  break;
 case 'E': /* Increase the emissive light of the object. */
  if(_my_shape != 1){
   if((emissive_color[0]+_EMISSION_CONSTANT) > 1){
    emissive_color[0] = 1;
   }else{
    emissive_color[0] += _EMISSION_CONSTANT;
   }

   if((emissive_color[1]+_EMISSION_CONSTANT) > 1){
    emissive_color[1] = 1;
   }else{
    emissive_color[1] += _EMISSION_CONSTANT;
   }

   if((emissive_color[2]+_EMISSION_CONSTANT) > 1){
    emissive_color[2] = 1;
   }else{
    emissive_color[2] += _EMISSION_CONSTANT;
   }
  }else{
   for(int i=0; i < _polygons_current; i++){ //Over all Polygons

    double* ep = _Polygons[i]->getEmissiveColor();

    if((ep[0]+_EMISSION_CONSTANT) > 1){
     ep[0] = 1;
    }else{
     ep[0] += _EMISSION_CONSTANT;
    }

    if((ep[1]+_EMISSION_CONSTANT) > 1){
     ep[1] = 1;
    }else{
     ep[1] += _EMISSION_CONSTANT;
    }

    if((ep[2]+_EMISSION_CONSTANT) > 1){
     ep[2] = 1;
    }else{
     ep[2] += _EMISSION_CONSTANT;
    }
   }
  }
  break;
 case 'p': /* Rotate the positional light about the Z-axis */
  glLoadIdentity();
  if(rotation_int == 7){
   rotation_int = 0;
  }else{
   rotation_int++;
  }
  glLightfv(GL_LIGHT0, GL_POSITION, _z_axis_rotations[rotation_int]);
  break;
 case 'P': /* Rotate the positional light about the Z-axis */
  glLoadIdentity();
  if(rotation_int == 0){
   rotation_int = 7;
  }else{
   rotation_int--;
  }
  glLightfv(GL_LIGHT0, GL_POSITION, _z_axis_rotations[rotation_int]);
  break;
 case 'o': /* Rotate the objects around the Y-axis : negative */
  _object_y_rotation -= 15.0;
  break;
 case 'O': /* Rotate the objects around the Y-axis : positive */
  _object_y_rotation += 15.0;
  break;
 case 'q': case 'Q': /* Quit the program */
  exit(0);
 }

 //Call redisplay to draw changes
 glutPostRedisplay();
}

void DrawFromFile(){

 glPushMatrix();

 for(int i=0; i < _polygons_current; i++){ //Over all Polygons

  double* ap = _Polygons[i]->getAmbientReflection();
  double* dp = _Polygons[i]->getDiffuseReflection();
  double* ep = _Polygons[i]->getEmissiveColor();
  double* sp = _Polygons[i]->getSpecularReflection();
  GLfloat amt[] = {ap[0], ap[1], ap[2], 1};
  GLfloat dif[] = {dp[0], dp[1], dp[2], 1};
  GLfloat emc[] = {ep[0], ep[1], ep[2], 1};
  GLfloat spc[] = {sp[0], sp[1], sp[2], 1};

  int _p_sides = _Polygons[i]->getSides();

  glMaterialfv(GL_FRONT, GL_AMBIENT, amt);
  glMaterialfv(GL_FRONT, GL_DIFFUSE, dif);
  glMaterialfv(GL_FRONT, GL_EMISSION, emc);
  glMaterialfv(GL_FRONT, GL_SPECULAR, spc);
  glMateriali(GL_FRONT, GL_SHININESS, _Polygons[i]->getSpecularExponent());

  glBegin(GL_POLYGON);

  for(int j=0; j < _p_sides; j++){

   glNormal3dv(_Polygons[i]->getSurfaceNormals());
   glVertex3dv(_Polygons[i]->getVertex(j));
  }

  glEnd();

 }

 glPopMatrix();

}

void Display(void){

 glClear( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT );
 glShadeModel (GL_SMOOTH);

 //Perspective data here
 glMatrixMode(GL_PROJECTION);
 gluPerspective(45, 1, 0, 2);

 glMatrixMode(GL_MODELVIEW);
 glLoadIdentity();

 glPushMatrix();

 switch(_my_shape){

 case 1:
  glTranslated(0, 0, -1);
  glRotated(_object_y_rotation, 0, 1, 0);
  DrawFromFile();
  break;
 case 2:
  glMaterialfv(GL_FRONT, GL_AMBIENT, ambient_reflection);
  glMaterialfv(GL_FRONT, GL_DIFFUSE, diffuse_reflection);
  glMaterialfv(GL_FRONT, GL_EMISSION, emissive_color);
  glMaterialfv(GL_FRONT, GL_SPECULAR, specular_reflection);
  glMateriali(GL_FRONT, GL_SHININESS, specular_exponent);
  glRotated(_object_y_rotation, 0, 1, 0);
  glutSolidTeapot(0.8);
  break;
 case 3:
  glMaterialfv(GL_FRONT, GL_AMBIENT, ambient_reflection);
  glMaterialfv(GL_FRONT, GL_DIFFUSE, diffuse_reflection);
  glMaterialfv(GL_FRONT, GL_EMISSION, emissive_color);
  glMaterialfv(GL_FRONT, GL_SPECULAR, specular_reflection);
  glMateriali(GL_FRONT, GL_SHININESS, specular_exponent);
  glRotated(_object_y_rotation, 0, 1, 0);
  glutSolidIcosahedron();
  break;
 case 4:
  glMaterialfv(GL_FRONT, GL_AMBIENT, ambient_reflection);
  glMaterialfv(GL_FRONT, GL_DIFFUSE, diffuse_reflection);
  glMaterialfv(GL_FRONT, GL_EMISSION, emissive_color);
  glMaterialfv(GL_FRONT, GL_SPECULAR, specular_reflection);
  glMateriali(GL_FRONT, GL_SHININESS, specular_exponent);
  glRotated(_object_y_rotation, 0, 1, 0);
  glutSolidTorus(0.3, 0.8, 10, 30);
  break;
 default:
  cout << _CHOICE_INVALID_ERROR << endl;
  exit(1);
  break;
 }

 glPopMatrix();

 glFlush();

}

int PollUser(){

 int choice = 0;

 cout << "Use the menu below to pick a shape to draw:" << endl << endl;
 cout << "1: Dodecahedron (Drawn from file)" << endl;
 cout << "2: Teapot (GLUT drawn)" << endl;
 cout << "3: Icosahedron (GLUT drawn)" << endl;
 cout << "4: Torus (GLUT drawn)" << endl;
 cout << endl << "Enter choice: ";
 cin >> choice;

 return choice;
}

int main(int argc, char** argv){

 _my_shape = PollUser();
 InitializeWindow(argc, argv); /* Initialize window */
 InitializeEnvironment(); /* Initialize other parameter */
 glutDisplayFunc(Display); /* Redisplay callback event handling */
 glutKeyboardFunc(Keyboard); /* Keyboard callback function */

 ReadFromFile(); /* Read from file */

 glutMainLoop(); /* Start glut functions */

 return 0;
}
```

<p>Polygon.h</p>

```#ifndef POLYGON_H_
#define POLYGON_H_

#include <iostream>
#include <cstdlib>
#include <new>

class Polygon {
public:
 Polygon();
 Polygon(int, double**);
 virtual ~Polygon();
 void *operator new(size_t size);
 void operator delete(void *p);
 void *operator new[](size_t size);
 void operator delete[](void *p);
 double* getVertex(int);
 void setSpecularExponent(int);
 void setSurfaceNormals(double,double,double);
 void setAmbientReflection(double,double,double);
 void setDiffuseReflection(double,double,double);
 void setSpecularReflection(double,double,double);
 void setEmissiveColor(double,double,double);
 int getSides(void);
 int getSpecularExponent(void);
 double* getSurfaceNormals(void);
 double* getAmbientReflection(void);
 double* getDiffuseReflection(void);
 double* getSpecularReflection(void);
 double* getEmissiveColor(void);

private:
 double** verticies;
 double surface_normals[3];
 double ambient_reflection[3];
 double diffuse_reflection[3];
 double specular_reflection[3];
 double emissive_color[3];
 int sides;
 int spec_ex;
};

#endif /* POLYGON_H_ */
```

<p>Polygon.cpp</p>

```#include "Polygon.h"

using namespace std;

Polygon::Polygon(){

 sides = 0;
}

Polygon::Polygon(int numberOfSides, double** polyVerticies){

 sides = numberOfSides;
 verticies = new double*[numberOfSides];

 for(int n=0; n<numberOfSides; n++){
  verticies[n] = new double[3];
  verticies[n][0] = polyVerticies[n][0];
  verticies[n][1] = polyVerticies[n][1];
  verticies[n][2] = polyVerticies[n][2];
 }
}

void *Polygon::operator new(size_t size){

 void *p;

 p =  malloc(size);
 if(!p) {
  bad_alloc ba;
  throw ba;
 }
 return p;
}

void Polygon::operator delete(void *p){

 free(p);
}

// new overloaded for loc arrays.
void *Polygon::operator new[](size_t size){

 void *p;

 p =  malloc(size);
 if(!p) {
  bad_alloc ba;
  throw ba;
 }
 return p;
}

void Polygon::operator delete[](void *p){

 free(p);
}

void Polygon::setSpecularExponent(int exponent){

 spec_ex = exponent;
}

void Polygon::setSurfaceNormals(double x, double y, double z){

 surface_normals[0] = x;
 surface_normals[1] = y;
 surface_normals[2] = z;
}

void Polygon::setAmbientReflection(double r, double g, double b){

 ambient_reflection[0] = r;
 ambient_reflection[1] = g;
 ambient_reflection[2] = b;
}

void Polygon::setDiffuseReflection(double r, double g, double b){

 diffuse_reflection[0] = r;
 diffuse_reflection[1] = g;
 diffuse_reflection[2] = b;
}

void Polygon::setSpecularReflection(double r, double g, double b){

 specular_reflection[0] = r;
 specular_reflection[1] = g;
 specular_reflection[2] = b;
}

void Polygon::setEmissiveColor(double r, double g, double b){

 emissive_color[0] = r;
 emissive_color[1] = g;
 emissive_color[2] = b;
}

double* Polygon::getVertex(int index){

 if(index < sides){

  double* _temp = new double[3];

  _temp[0] = verticies[index][0];
  _temp[1] = verticies[index][1];
  _temp[2] = verticies[index][2];

  return _temp;
 }

 return new double;
}

int Polygon::getSides(){

 return sides;
}

int Polygon::getSpecularExponent(){

 return spec_ex;
}

double* Polygon::getSurfaceNormals(){

 return surface_normals;
}

double* Polygon::getAmbientReflection(){

 return ambient_reflection;
}

double* Polygon::getDiffuseReflection(){

 return diffuse_reflection;
}

double* Polygon::getSpecularReflection(){

 return specular_reflection;
}

double* Polygon::getEmissiveColor(){

 return emissive_color;
}

Polygon::~Polygon() {
 delete[] verticies;
}
```

Thanks for any help anyone can offer.

答: Your Error is caused by there being a polygon type already defined in a windows system file.  Put your Polygon type in a namespace and fully qualifie it. </p>

ContentLicense: CC BY-SA 2.5

Body:
I'm not new to C++ but I am used to running a g++ compiler vs Microsoft's VS C++. I understand what this error should mean. It should mean that I'm missing a ';' on the line before or in the class Polygon. I can't seem to find anything wrong. g++ compiles the code without error. It seems like the Polygon Class isn't being loaded. Can anyone please show me what I'm missing please.I have the Application.cpp, Polygon.h, and Polygon.cpp below.

Application.cpp throwing errors but if I can fix the first others will follow:

application.cpp(121) : error C2143: syntax error : missing ';' before '*'

application.cpp(121) : error C4430: missing type specifier - int assumed. Note: C++ does not support default-int

application.cpp(121) : error C2365: 'Polygon' : redefinition; previous definition was 'function'
c:\program files\microsoft sdks\windows\v6.0a\include\wingdi.h(4203) : see declaration of 'Polygon'

#include <sstream>
#include <numeric>
#include <math.h>
#include "Polygon.h"

#define PI 3.14159265

//use standard namespace
using namespace std;

 /**************************** Window Variables ****************************/

double _window_height   = 500;
double _window_width   = 500;
double _window_position_x  = 0;
double _window_position_y  = 0;

string _window_title ("Assignment 5");

/**************************** Object Variables ****************************/

int _my_shape     = 0;
GLint _object_shine    = 40;
double _object_y_rotation  = 0;

GLfloat ambient_reflection[3] = {1.0, 1.0, 1.0};
GLfloat diffuse_reflection[3] = {1.0, 1.0, 1.0};
GLfloat specular_reflection[3] = {1.0, 1.0, 1.0};
GLfloat emissive_color[3]  = {0.0, 0.0, 0.0};
int specular_exponent   = 0;

/*************************** Lighting Variables ***************************/

//Global Light settings

GLfloat _global_ambient_light[] = {0.5, 0.5, 0.5, 1.0};
GLfloat _global_diffuse_light[] = {0.7, 0.7, 0.7, 1.0};

int rotation_int     = 0;
int rotation_angle    = 90;
int _CAMERA_DISTANCE   = 2;

//Light 0 Settings

GLfloat _z_axis_rotations[8][4] = {{(_CAMERA_DISTANCE*cos((90)*PI/180)), (_CAMERA_DISTANCE*sin((90)*PI/180)), 0.0, 1.0},
         {(_CAMERA_DISTANCE*cos((45)*PI/180)), (_CAMERA_DISTANCE*sin((45)*PI/180)), 0.0, 1.0},
         {(_CAMERA_DISTANCE*cos((0)*PI/180)), (_CAMERA_DISTANCE*sin((0)*PI/180)), 0.0, 1.0},
         {(_CAMERA_DISTANCE*cos((315)*PI/180)), (_CAMERA_DISTANCE*sin((315)*PI/180)), 0.0, 1.0},
         {(_CAMERA_DISTANCE*cos((270)*PI/180)), (_CAMERA_DISTANCE*sin((270)*PI/180)), 0.0, 1.0},
         {(_CAMERA_DISTANCE*cos((225)*PI/180)), (_CAMERA_DISTANCE*sin((225)*PI/180)), 0.0, 1.0},
         {(_CAMERA_DISTANCE*cos((180)*PI/180)), (_CAMERA_DISTANCE*sin((180)*PI/180)), 0.0, 1.0},
         {(_CAMERA_DISTANCE*cos((135)*PI/180)), (_CAMERA_DISTANCE*sin((135)*PI/180)), 0.0, 1.0}};

GLfloat _ambient_0_light[]   = {0.3f, 0.3f, 0.3f, 1.0f};
GLfloat _diffuse_0_light[]   = {0.6f, 0.6f, 0.6f, 1.0f};
GLfloat _specular_0_light[]  = {0.6f, 0.6f, 0.6f, 1.0f};
GLfloat _specular_0_property[]  = {0.6f, 0.6f, 0.6f, 1.0f};

//Light 1 Settings

// Green Spotlight with narrow angle
GLfloat _light_1_position[]  = {2.0, 0.0, -0.5, 1.0};
GLfloat _diffuse_1_light[]   = {0.2, 0.4, 0.9, 1.0};
GLfloat _spot_1_direction[]  = {-0.3, -2.0, -0.3};

//Light 2 Settings

// Red Spotlight with wide angle
GLfloat _light_2_position[]  = {0.3, -0.5, 4.0, 1.0};
GLfloat _diffuse_2_light[]   = {1.0, 0.2, 0.6, 1.0};
GLfloat _spot_2_direction[]  = {0.3, -0.5, -2.0};

GLfloat _cutoff     = 90.0;

GLfloat _AMBIENT_CONSTANT  = 0.1;
GLfloat _DIFFUSE_CONSTANT  = 0.1;
GLfloat _EMISSION_CONSTANT  = 0.05;
GLfloat _SPECULAR_CONSTANT  = 0.1;
int _SPECULAR_EXPONENT_CONSTANT = 1;
int _CUTOFF_CONSTANT   = 1;

/*************************** Shading Variables ***************************/

bool _shade_model_smooth  = true;

/**************************** File Variables *****************************/

//Error String printed if the file is not found
string _FILE_OPEN_ERROR = "Error: File could not be found or opened.";

//Error String printed if the file is not formed correctly
string _CHOICE_INVALID_ERROR = "Error: The choice you made was not one that is defined.";

/** for file reading **/
//The Array for holding all the Polygons
Polygon** _Polygons;
//the current size of the Polygon Array
int _polygons_max = 10;
//the current element for processing in the Polygon Array
int _polygons_current = 0;

/* ReadFromFile
 *
 * This method will ask a filename from the user and either return to
 * the user a file not found error or will read in from the file the
 * coordinates and place them in the coordinate array, while also setting
 * the number of lines that make up a shape.
 */
void ReadFromFile(){

 ifstream input; //  input file stream
 string filename = ""; //  used to store filename
 string line = ""; // temporary storage for reading lines at a time

 // cout << "Type a filename and press Enter: ";
 // cin >> filename;
 //cout << "Type a filename and press Enter: dodecahedron.dat" << endl;
 filename = "dodec.dat";//"dodecahedron.dat"; //should be 36 polygons

 input.open (filename.c_str(), ifstream::in);//try to open the file
 if(input.is_open()){ //check if file is open

  _Polygons = new Polygon*[_polygons_max];

  double _light_settings[12] = {0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0};
  int SH = 0;
  double _normals[3] = {0.0, 0.0, 0.0};

  int _coordinate_count = 0;
  int _coordinate_max = 4;
  double** _coordinates = new double*[_coordinate_max];

  while (input.good()){ //not eof or failbit

   /* Ensure space is available */
   if(_polygons_current >= _polygons_max){

    _polygons_max = _polygons_max * 2; //double max size
    Polygon** temp = new Polygon*[_polygons_max]; //create bigger array

    for (int j = 0; j <_polygons_current; j++) {
     temp[j] = _Polygons[j]; // copy values to new array.
    }

    delete [] _Polygons; //free old array memory
    _Polygons = temp; //transfer polygons
   }

   getline(input, line); //get the line from input

   string::size_type _last_pos = line.find_first_not_of(" ", 0);
   string::size_type _pos = line.find_first_of(" ", _last_pos);

   if((line.substr(_last_pos, _pos - _last_pos)).c_str()[0] == '#'){ //comment
    //do nothing for this line
   }else if((line.substr(_last_pos, _pos - _last_pos)).c_str()[0] == 'J' ||
     (line.substr(_last_pos, _pos - _last_pos)).c_str()[0] == 'j'){ //polygon start

    if(_coordinate_count != 0){

     //cout << "Polygon #" << _polygons_current << endl;

     _Polygons[_polygons_current] = new Polygon(_coordinate_count, _coordinates);
     _Polygons[_polygons_current]->setAmbientReflection(_light_settings[0], _light_settings[1], _light_settings[2]);
     _Polygons[_polygons_current]->setDiffuseReflection(_light_settings[3], _light_settings[4], _light_settings[5]);
     _Polygons[_polygons_current]->setSpecularReflection(_light_settings[6], _light_settings[7], _light_settings[8]);
     _Polygons[_polygons_current]->setEmissiveColor(_light_settings[9], _light_settings[10], _light_settings[11]);
     _Polygons[_polygons_current]->setSurfaceNormals(_normals[0], _normals[1], _normals[2]);
     _Polygons[_polygons_current]->setSpecularExponent(SH);

     for(int i=0; i<_coordinate_count; i++){
      delete _coordinates[i];
     }

     _coordinate_count = 0;
     _polygons_current++;
    }

    if(line.find_first_not_of(" ", _pos) != string::npos){

     for(int i=0; i<12; i++){
      _last_pos = line.find_first_not_of(" ", _pos);
      _pos = line.find_first_of(" ", _last_pos);
      _light_settings[i] = atof(line.substr(_last_pos, _pos - _last_pos).c_str());
     }

     _last_pos = line.find_first_not_of(" ", _pos);
     _pos = line.find_first_of(" ", _last_pos);
     SH = atoi(line.substr(_last_pos, _pos - _last_pos).c_str());

     for(int i=0; i<3; i++){
      _last_pos = line.find_first_not_of(" ", _pos);
      _pos = line.find_first_of(" ", _last_pos);
      _normals[i] = atof(line.substr(_last_pos, _pos - _last_pos).c_str());
     }
    }

   }else{

    /* Ensure space is available */
    if(_coordinate_count >= _coordinate_max){

     _coordinate_max = _coordinate_max * 2; //double max size
     double** temp = new double*[_coordinate_max]; //create bigger array

     for (int i = 0; i < _coordinate_count; i++) {
      temp[i] = new double[3];
      temp[i][0] = _coordinates[i][0]; // copy values to new array.
      temp[i][1] = _coordinates[i][1];
      temp[i][2] = _coordinates[i][3];
     }

     delete [] _coordinates; //free old array memory
     _coordinates = temp; //transfer polygons
    }

    _coordinates[_coordinate_count] = new double[3];

    for(int i=0; i<3; i++){
     _coordinates[_coordinate_count][i] = atof(line.substr(_last_pos, _pos - _last_pos).c_str());
     _last_pos = line.find_first_not_of(" ", _pos);
     _pos = line.find_first_of(" ", _last_pos);
    }
    _coordinate_count++;
   }
  }

  input.close();

 }else{

  //if the file could not be opened output to the screen the error
  cout << _FILE_OPEN_ERROR;
  exit(0);
 }
}

/* InitializeWindow
 *
 * Initializes the GLUT Library settings and creates a window for the
 * program to be displayed in.
 *
 */
void InitializeWindow(int argc, char** argv){

 glutInit(&argc,argv); /* Initialize GLUT */
 glutInitDisplayMode( GLUT_RGB | GLUT_SINGLE | GLUT_DEPTH );/* Specify display mode */
 glutInitWindowSize(_window_width, _window_height); /* Set window size */
 glutInitWindowPosition(_window_position_x, _window_position_y); /* Set window position */
 glutCreateWindow(_window_title.c_str()); /* Create Window */
}

/* InitializeEnvironment
 *
 * Initializes the Glut environment in which the drawing is to be done.
 */
void InitializeEnvironment(){

 glClearColor (0.0, 0.0, 0.0, 0.0);
 glMatrixMode(GL_MODELVIEW);
 glLoadIdentity();

 glLightModelfv(GL_LIGHT_MODEL_AMBIENT, _global_ambient_light);
 glMaterialfv(GL_FRONT, GL_AMBIENT_AND_DIFFUSE, _global_diffuse_light);

 glLoadIdentity();
 glLightfv(GL_LIGHT0, GL_POSITION, _z_axis_rotations[0]);
 glLightfv(GL_LIGHT0, GL_SPECULAR, _specular_0_light);
 glLightf(GL_LIGHT0, GL_SPOT_CUTOFF, _cutoff);
 glLightf(GL_LIGHT0, GL_SPOT_EXPONENT, 0);

 glLoadIdentity();
 glLightfv(GL_LIGHT1, GL_POSITION, _light_1_position);
 glLightfv(GL_LIGHT1, GL_DIFFUSE, _diffuse_1_light);
 //
 // glLoadIdentity();
 // glLightfv(GL_LIGHT2, GL_POSITION, light3_position);
 // glLightfv(GL_LIGHT2, GL_DIFFUSE, light3_diffuse_light);

 glEnable(GL_LIGHTING);
 glEnable(GL_DEPTH_TEST);

 glEnable(GL_LIGHT0);
 glEnable(GL_LIGHT1);

 if(_my_shape == 1){
  glFrontFace(GL_CW);
 }else{
  glFrontFace(GL_CCW);
 }

 glEnable(GL_CULL_FACE);

}

// In the main method we registered this method as the callback function for
// Keyboard input.  Anytime a key is pressed the ascii value of the key and
// the x and y positions of the mouse cursor within the window are passed to
// this function.
void Keyboard(unsigned char key, int x, int y) {

 switch (key) {
 case '1':
  glEnable(GL_LIGHT0);
  break;
 case '2':
  glEnable(GL_LIGHT1);
  break;
 case '+': /* Increase the cutoff angle of the positional light. */
  if(_cutoff == 90){
   _cutoff = 180;
  }else if((_cutoff-_CUTOFF_CONSTANT) > 180){
   _cutoff = 180;
  }else{
   _cutoff += _CUTOFF_CONSTANT;
  }
  glLightf(GL_LIGHT0, GL_SPOT_CUTOFF, _cutoff);
  break;
 case '-': /* Decrease the cutoff angle of the positional light. */
  if(_cutoff == 180){
   _cutoff = 90;
  }else if((_cutoff-_CUTOFF_CONSTANT) < 0){
   _cutoff = 0;
  }else{
   _cutoff -= _CUTOFF_CONSTANT;
  }
  glLightf(GL_LIGHT0, GL_SPOT_CUTOFF, _cutoff);
  break;
 case '0': /* Turn off the directional and positional light. */
  glDisable(GL_LIGHT0);
  glDisable(GL_LIGHT1);
  break;
 case 'a': /* Decrease the ambient light. */
  if(_global_ambient_light[0]>0){
   _global_ambient_light[0] = _global_ambient_light[1] = _global_ambient_light[2] -= _AMBIENT_CONSTANT;
   glLightModelfv(GL_LIGHT_MODEL_AMBIENT, _global_ambient_light);
  }
  break;
 case 'A': /* Increase the ambient light. */
  if(_global_ambient_light[0]<1){
   _global_ambient_light[0] = _global_ambient_light[1] = _global_ambient_light[2] += _AMBIENT_CONSTANT;
   glLightModelfv(GL_LIGHT_MODEL_AMBIENT, _global_ambient_light);
  }
  break;
 case 'd': /* Decrease the diffuse light. */
  if(_global_diffuse_light[0]>0){
   _global_diffuse_light[0] = _global_diffuse_light[1] = _global_diffuse_light[2] -= _DIFFUSE_CONSTANT;
   glMaterialfv(GL_FRONT, GL_AMBIENT_AND_DIFFUSE, _global_diffuse_light);
  }
  break;
 case 'D': /* Increase the diffuse light. */
  if(_global_diffuse_light[0]<1){
   _global_diffuse_light[0] = _global_diffuse_light[1] = _global_diffuse_light[2] += _DIFFUSE_CONSTANT;
   glMaterialfv(GL_FRONT, GL_AMBIENT_AND_DIFFUSE, _global_diffuse_light);
  }
  break;
 case 's': /* Decrease the specular component of the positional light. */
  if(_my_shape != 1){
   for(int i=0; i<3; i++){
    if((specular_reflection[i]-_SPECULAR_CONSTANT) < -1.0){
     specular_reflection[i] = -1.0;
    }else{
     specular_reflection[i] -= _SPECULAR_CONSTANT;
    }
   }
  }else{
   for(int i=0; i < _polygons_current; i++){ //Over all Polygons

    double* sr = _Polygons[i]->getSpecularReflection();

    for(int j=0; j<3; j++){
     if((sr[j]-_SPECULAR_CONSTANT) < -1.0){
      sr[j] = -1.0;
     }else{
      sr[j] -= _SPECULAR_CONSTANT;
     }
    }
   }
  }
  break;
 case 'S': /* Increase the specular component of the positional light. */
  if(_my_shape != 1){
   for(int i=0; i<3; i++){
    if((specular_reflection[i]+_SPECULAR_CONSTANT) > 1.0){
     specular_reflection[i] = 1.0;
    }else{
     specular_reflection[i] += _SPECULAR_CONSTANT;
    }
   }
  }else{
   for(int i=0; i < _polygons_current; i++){ //Over all Polygons

    double* sr = _Polygons[i]->getSpecularReflection();

    for(int j=0; j<3; j++){
     if((sr[j]+_SPECULAR_CONSTANT) > 1.0){
      sr[j] = 1.0;
     }else{
      sr[j] += _SPECULAR_CONSTANT;
     }
    }
   }
  }
  break;
 case 'h': /* Decrease the shininess of the object. */
  if(_my_shape != 1){
   if((specular_exponent-_SPECULAR_EXPONENT_CONSTANT) < 0){
    specular_exponent = 0;
   }else{
    specular_exponent-=_SPECULAR_EXPONENT_CONSTANT;
   }
  }else{
   for(int i=0; i < _polygons_current; i++){ //Over all Polygons

    int sh = _Polygons[i]->getSpecularExponent();

    if((sh-_SPECULAR_EXPONENT_CONSTANT) < 0){
     _Polygons[i]->setSpecularExponent(0);
    }else{
     _Polygons[i]->setSpecularExponent(sh-_SPECULAR_EXPONENT_CONSTANT);
    }
   }
  }
  break;
 case 'H': /* Increase the shininess of the object. */
  if(_my_shape != 1){
   if((specular_exponent+_SPECULAR_EXPONENT_CONSTANT) > 128){
    specular_exponent = 128;
   }else{
    specular_exponent+=_SPECULAR_EXPONENT_CONSTANT;
   }
  }else{
   for(int i=0; i < _polygons_current; i++){ //Over all Polygons

    int sh = _Polygons[i]->getSpecularExponent();

    if((sh+_SPECULAR_EXPONENT_CONSTANT) > 128){
     _Polygons[i]->setSpecularExponent(128);
    }else{
     _Polygons[i]->setSpecularExponent(sh+_SPECULAR_EXPONENT_CONSTANT);
    }
   }
  }
  break;
 case 'e': /* Decrease the emissive light of the object. */
  if(_my_shape != 1){
   if((emissive_color[0]-_EMISSION_CONSTANT) < 0){
    emissive_color[0] = 0;
   }else{
    emissive_color[0] -= _EMISSION_CONSTANT;
   }

   if((emissive_color[1]-_EMISSION_CONSTANT) < 0){
    emissive_color[1] = 0;
   }else{
    emissive_color[1] -= _EMISSION_CONSTANT;
   }

   if((emissive_color[2]-_EMISSION_CONSTANT) < 0){
    emissive_color[2] = 0;
   }else{
    emissive_color[2] -= _EMISSION_CONSTANT;
   }
  }else{
   for(int i=0; i < _polygons_current; i++){ //Over all Polygons

    double* ep = _Polygons[i]->getEmissiveColor();

    if((ep[0]-_EMISSION_CONSTANT) < 0){
     ep[0] = 0;
    }else{
     ep[0] -= _EMISSION_CONSTANT;
    }

    if((ep[1]-_EMISSION_CONSTANT) < 0){
     ep[1] = 0;
    }else{
     ep[1] -= _EMISSION_CONSTANT;
    }

    if((ep[2]-_EMISSION_CONSTANT) < 0){
     ep[2] = 0;
    }else{
     ep[2] -= _EMISSION_CONSTANT;
    }
   }
  }
  break;
 case 'E': /* Increase the emissive light of the object. */
  if(_my_shape != 1){
   if((emissive_color[0]+_EMISSION_CONSTANT) > 1){
    emissive_color[0] = 1;
   }else{
    emissive_color[0] += _EMISSION_CONSTANT;
   }

   if((emissive_color[1]+_EMISSION_CONSTANT) > 1){
    emissive_color[1] = 1;
   }else{
    emissive_color[1] += _EMISSION_CONSTANT;
   }

   if((emissive_color[2]+_EMISSION_CONSTANT) > 1){
    emissive_color[2] = 1;
   }else{
    emissive_color[2] += _EMISSION_CONSTANT;
   }
  }else{
   for(int i=0; i < _polygons_current; i++){ //Over all Polygons

    double* ep = _Polygons[i]->getEmissiveColor();

    if((ep[0]+_EMISSION_CONSTANT) > 1){
     ep[0] = 1;
    }else{
     ep[0] += _EMISSION_CONSTANT;
    }

    if((ep[1]+_EMISSION_CONSTANT) > 1){
     ep[1] = 1;
    }else{
     ep[1] += _EMISSION_CONSTANT;
    }

    if((ep[2]+_EMISSION_CONSTANT) > 1){
     ep[2] = 1;
    }else{
     ep[2] += _EMISSION_CONSTANT;
    }
   }
  }
  break;
 case 'p': /* Rotate the positional light about the Z-axis */
  glLoadIdentity();
  if(rotation_int == 7){
   rotation_int = 0;
  }else{
   rotation_int++;
  }
  glLightfv(GL_LIGHT0, GL_POSITION, _z_axis_rotations[rotation_int]);
  break;
 case 'P': /* Rotate the positional light about the Z-axis */
  glLoadIdentity();
  if(rotation_int == 0){
   rotation_int = 7;
  }else{
   rotation_int--;
  }
  glLightfv(GL_LIGHT0, GL_POSITION, _z_axis_rotations[rotation_int]);
  break;
 case 'o': /* Rotate the objects around the Y-axis : negative */
  _object_y_rotation -= 15.0;
  break;
 case 'O': /* Rotate the objects around the Y-axis : positive */
  _object_y_rotation += 15.0;
  break;
 case 'q': case 'Q': /* Quit the program */
  exit(0);
 }

 //Call redisplay to draw changes
 glutPostRedisplay();
}

void DrawFromFile(){

 glPushMatrix();

 for(int i=0; i < _polygons_current; i++){ //Over all Polygons

  double* ap = _Polygons[i]->getAmbientReflection();
  double* dp = _Polygons[i]->getDiffuseReflection();
  double* ep = _Polygons[i]->getEmissiveColor();
  double* sp = _Polygons[i]->getSpecularReflection();
  GLfloat amt[] = {ap[0], ap[1], ap[2], 1};
  GLfloat dif[] = {dp[0], dp[1], dp[2], 1};
  GLfloat emc[] = {ep[0], ep[1], ep[2], 1};
  GLfloat spc[] = {sp[0], sp[1], sp[2], 1};

  int _p_sides = _Polygons[i]->getSides();

  glMaterialfv(GL_FRONT, GL_AMBIENT, amt);
  glMaterialfv(GL_FRONT, GL_DIFFUSE, dif);
  glMaterialfv(GL_FRONT, GL_EMISSION, emc);
  glMaterialfv(GL_FRONT, GL_SPECULAR, spc);
  glMateriali(GL_FRONT, GL_SHININESS, _Polygons[i]->getSpecularExponent());

  glBegin(GL_POLYGON);

  for(int j=0; j < _p_sides; j++){

   glNormal3dv(_Polygons[i]->getSurfaceNormals());
   glVertex3dv(_Polygons[i]->getVertex(j));
  }

  glEnd();

 }

 glPopMatrix();

}

void Display(void){

 glClear( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT );
 glShadeModel (GL_SMOOTH);

 //Perspective data here
 glMatrixMode(GL_PROJECTION);
 gluPerspective(45, 1, 0, 2);

 glMatrixMode(GL_MODELVIEW);
 glLoadIdentity();

 glPushMatrix();

 switch(_my_shape){

 case 1:
  glTranslated(0, 0, -1);
  glRotated(_object_y_rotation, 0, 1, 0);
  DrawFromFile();
  break;
 case 2:
  glMaterialfv(GL_FRONT, GL_AMBIENT, ambient_reflection);
  glMaterialfv(GL_FRONT, GL_DIFFUSE, diffuse_reflection);
  glMaterialfv(GL_FRONT, GL_EMISSION, emissive_color);
  glMaterialfv(GL_FRONT, GL_SPECULAR, specular_reflection);
  glMateriali(GL_FRONT, GL_SHININESS, specular_exponent);
  glRotated(_object_y_rotation, 0, 1, 0);
  glutSolidTeapot(0.8);
  break;
 case 3:
  glMaterialfv(GL_FRONT, GL_AMBIENT, ambient_reflection);
  glMaterialfv(GL_FRONT, GL_DIFFUSE, diffuse_reflection);
  glMaterialfv(GL_FRONT, GL_EMISSION, emissive_color);
  glMaterialfv(GL_FRONT, GL_SPECULAR, specular_reflection);
  glMateriali(GL_FRONT, GL_SHININESS, specular_exponent);
  glRotated(_object_y_rotation, 0, 1, 0);
  glutSolidIcosahedron();
  break;
 case 4:
  glMaterialfv(GL_FRONT, GL_AMBIENT, ambient_reflection);
  glMaterialfv(GL_FRONT, GL_DIFFUSE, diffuse_reflection);
  glMaterialfv(GL_FRONT, GL_EMISSION, emissive_color);
  glMaterialfv(GL_FRONT, GL_SPECULAR, specular_reflection);
  glMateriali(GL_FRONT, GL_SHININESS, specular_exponent);
  glRotated(_object_y_rotation, 0, 1, 0);
  glutSolidTorus(0.3, 0.8, 10, 30);
  break;
 default:
  cout << _CHOICE_INVALID_ERROR << endl;
  exit(1);
  break;
 }

 glPopMatrix();

 glFlush();

}

int PollUser(){

 int choice = 0;

 cout << "Use the menu below to pick a shape to draw:" << endl << endl;
 cout << "1: Dodecahedron (Drawn from file)" << endl;
 cout << "2: Teapot (GLUT drawn)" << endl;
 cout << "3: Icosahedron (GLUT drawn)" << endl;
 cout << "4: Torus (GLUT drawn)" << endl;
 cout << endl << "Enter choice: ";
 cin >> choice;

 return choice;
}

int main(int argc, char** argv){

 _my_shape = PollUser();
 InitializeWindow(argc, argv); /* Initialize window */
 InitializeEnvironment(); /* Initialize other parameter */
 glutDisplayFunc(Display); /* Redisplay callback event handling */
 glutKeyboardFunc(Keyboard); /* Keyboard callback function */

 ReadFromFile(); /* Read from file */

 glutMainLoop(); /* Start glut functions */

 return 0;
}

Polygon.h

#ifndef POLYGON_H_
#define POLYGON_H_

#include <iostream>
#include <cstdlib>
#include <new>

class Polygon {
public:
 Polygon();
 Polygon(int, double**);
 virtual ~Polygon();
 void *operator new(size_t size);
 void operator delete(void *p);
 void *operator new[](size_t size);
 void operator delete[](void *p);
 double* getVertex(int);
 void setSpecularExponent(int);
 void setSurfaceNormals(double,double,double);
 void setAmbientReflection(double,double,double);
 void setDiffuseReflection(double,double,double);
 void setSpecularReflection(double,double,double);
 void setEmissiveColor(double,double,double);
 int getSides(void);
 int getSpecularExponent(void);
 double* getSurfaceNormals(void);
 double* getAmbientReflection(void);
 double* getDiffuseReflection(void);
 double* getSpecularReflection(void);
 double* getEmissiveColor(void);

private:
 double** verticies;
 double surface_normals[3];
 double ambient_reflection[3];
 double diffuse_reflection[3];
 double specular_reflection[3];
 double emissive_color[3];
 int sides;
 int spec_ex;
};

#endif /* POLYGON_H_ */

Polygon.cpp

#include "Polygon.h"

using namespace std;

Polygon::Polygon(){

 sides = 0;
}

Polygon::Polygon(int numberOfSides, double** polyVerticies){

 sides = numberOfSides;
 verticies = new double*[numberOfSides];

 for(int n=0; n<numberOfSides; n++){
  verticies[n] = new double[3];
  verticies[n][0] = polyVerticies[n][0];
  verticies[n][1] = polyVerticies[n][1];
  verticies[n][2] = polyVerticies[n][2];
 }
}

void *Polygon::operator new(size_t size){

 void *p;

 p =  malloc(size);
 if(!p) {
  bad_alloc ba;
  throw ba;
 }
 return p;
}

void Polygon::operator delete(void *p){

 free(p);
}

// new overloaded for loc arrays.
void *Polygon::operator new[](size_t size){

 void *p;

 p =  malloc(size);
 if(!p) {
  bad_alloc ba;
  throw ba;
 }
 return p;
}

void Polygon::operator delete[](void *p){

 free(p);
}

void Polygon::setSpecularExponent(int exponent){

 spec_ex = exponent;
}

void Polygon::setSurfaceNormals(double x, double y, double z){

 surface_normals[0] = x;
 surface_normals[1] = y;
 surface_normals[2] = z;
}

void Polygon::setAmbientReflection(double r, double g, double b){

 ambient_reflection[0] = r;
 ambient_reflection[1] = g;
 ambient_reflection[2] = b;
}

void Polygon::setDiffuseReflection(double r, double g, double b){

 diffuse_reflection[0] = r;
 diffuse_reflection[1] = g;
 diffuse_reflection[2] = b;
}

void Polygon::setSpecularReflection(double r, double g, double b){

 specular_reflection[0] = r;
 specular_reflection[1] = g;
 specular_reflection[2] = b;
}

void Polygon::setEmissiveColor(double r, double g, double b){

 emissive_color[0] = r;
 emissive_color[1] = g;
 emissive_color[2] = b;
}

double* Polygon::getVertex(int index){

 if(index < sides){

  double* _temp = new double[3];

  _temp[0] = verticies[index][0];
  _temp[1] = verticies[index][1];
  _temp[2] = verticies[index][2];

  return _temp;
 }

 return new double;
}

int Polygon::getSides(){

 return sides;
}

int Polygon::getSpecularExponent(){

 return spec_ex;
}

double* Polygon::getSurfaceNormals(){

 return surface_normals;
}

double* Polygon::getAmbientReflection(){

 return ambient_reflection;
}

double* Polygon::getDiffuseReflection(){

 return diffuse_reflection;
}

double* Polygon::getSpecularReflection(){

 return specular_reflection;
}

double* Polygon::getEmissiveColor(){

 return emissive_color;
}

Polygon::~Polygon() {
 delete[] verticies;
}

Thanks for any help anyone can offer.


问:
Can I call APIs in componentWillMount in React?
I'm working on react for last 1 year. The convention which we follow is make an API call in componentDidMount, fetch the data and setState after the data has come. This will ensure that the component has mounted and setting state will cause a re-render the component but I want to know why we can't setState in componentWillMount or constructor

The official documentation says that :

componentWillMount() is invoked immediately before mounting occurs. It
  is called before render(), therefore setting state in this method will
  not trigger a re-rendering. Avoid introducing any side-effects or
  subscriptions in this method.

it says setting state in this method will not trigger a re-rendering, which I don't want while making an API call. If I'm able to get the data and able to set in the state (assuming API calls are really fast) in componentWillMount or in constructor and data is present in the first render, why would I want a re-render at all?

and if the API call is slow, then setState will be async and componentWillMount has already returned then I'll be able to setState and a re-render should occur.

As a whole, I'm pretty much confused why we shouldn't make API calls in constructor or componentWillMount. Can somebody really help me understand how react works in such case?

答:
ComponentWillMount

Now that the props and state are set, we finally enter the realm of Life Cycle methods

That means React expects state to be available as render function will be called next and code can break if any mentioned state variable is missing which may occur in case of ajax.

Constructor

This is the place where you define.

So Calling an ajax will not update the values of any state as ajax is async and constructor will not wait for response. Ideally, you should use constructor to set default/initial values.

Ideally these functions should be pure function, only depending on parameters. Bringing ajax brings side effect to function.

Yes, functions depend on state and using this.setState can bring you such issues (You have set value in state but value is missing in state in next called function).

This makes code fragile. If your API is really fast, you can pass this value as an argument and in your component, check if this arg is available. If yes, initialise you state with it. If not, set it to default. Also, in success function of ajax, you can check for ref of this component. If it exist, component is rendered and you can call its state using setState  or any setter(preferred) function.

Also remember, when you say API calls are really fast, your server and processing may be at optimum speed, but you can never be sure with network.


问:
Efficiently wrapping a double
I have a number of geometric functions that only accept angles in the range 0° to 360°.  If the angle is outside that range then the angle is invalid (i.e. converting 365° to 5° is not an option) and there's no point in calling the functions.  To this end I've created the following class:

```<code>struct PositiveAngle {
    public let value: Double

    init?(value: Double) {
        guard 0.0 <= value && value <= 360.0 else {
            return nil
        }
        self.value = value
    }
}
</code>```

To be used as follows:

```<code>let angle = PositiveAngle(value: 30.0)
print(angle.value)

func foo(angle: PositiveAngle) -> PositiveAngle {
    ...
}
</code>```

This works but it feels "clunky" because I have extract the value of the angle from the struct whenever I need to use it.  Given that all I am after is a Double that has a restricted range, is there a more efficient way to achieve this?

答:
You could use a struct with a static function</p>

```<code>struct AngleChecker {
    static func validate(_ value : Double) -> Double? {
       return (0.0...360.0).contains(value) ? value : nil
    }
}

let x = AngleChecker.validate(12.0) // --> 12.0
let y = AngleChecker.validate(362.0) // --> nil
</code>```

Title: Efficiently wrapping a double

Body:
I have a number of geometric functions that only accept angles in the range 0° to 360°.  If the angle is outside that range then the angle is invalid (i.e. converting 365° to 5° is not an option) and there's no point in calling the functions.  To this end I've created the following class:

struct PositiveAngle {
    public let value: Double

    init?(value: Double) {
        guard 0.0 <= value && value <= 360.0 else {
            return nil
        }
        self.value = value
    }
}

To be used as follows:

let angle = PositiveAngle(value: 30.0)
print(angle.value)

func foo(angle: PositiveAngle) -> PositiveAngle {
    ...
}

This works but it feels "clunky" because I have extract the value of the angle from the struct whenever I need to use it.  Given that all I am after is a Double that has a restricted range, is there a more efficient way to achieve this?

Body:
You could use a struct with a static function

struct AngleChecker {
    static func validate(_ value : Double) -> Double? {
       return (0.0...360.0).contains(value) ? value : nil
    }
}

let x = AngleChecker.validate(12.0) // --> 12.0
let y = AngleChecker.validate(362.0) // --> nil


问:
Trying to do conditional validators with Angular2 form models. Attempting to use myForm.setValidators(), but doesn't seem to work
I've been trying to use the model form in an Ionic/Angular2. I have a form that I want to do some conditional validation. The user starts with 6 fields that are required and then can choose between 'manual' and 'automatic' processing. If 'automatic' is chosen, 3 more form inputs/selects are rendered. I'd like these 3 fields to go from being not required to required.

Here's the model to start:

```<code>this.myForm = this.formBuilder.group({
  name: ['', Validators.compose([Validators.required, Validators.maxLength(45), Validators.minLength(2)])],
  img: [''],
  longDescription: ['', Validators.compose([Validators.required, Validators.maxLength(200)])],
  shortDescription: ['', Validators.compose([Validators.required, Validators.maxLength(45)])],
  processingType: [this.PROCESSING_TYPE.MANUAL],
  discountType: ['' ],
  discountRule: ['' ],
  discountAmount: ['' ],  // money, isNumbersOnly handled by custom validator
  product: [''],
  dateRuleDays: ['' ],
  dateRuleTimeStart: ['' ],
  dateRuleTimeEnd: ['' ],

  startDate: ['', Validators.required],
  expiryDate: ['', Validators.required ]
});
</code>```

discountType, discountRule, discountAmount are the 3 fields that I'd like to toggle to being required.

Here's what I've tried:

markup where setProcessingType fn gets called (i can provide the full page if needed)

```<code><!-- automatic or manual -->
<h4 margin-top text-center>Processing Type</h4>
<ion-row text-center>
  <ion-col width-50>
      <button class="width-80" color="primary" (click)="setProcessingType(PROCESSING_TYPE.MANUAL)" ion-button margin-top>{{ PROCESSING_TYPE.MANUAL }}</button>
  </ion-col>
  <ion-col width-50>
      <button class="width-80" color="primary" (click)="setProcessingType(PROCESSING_TYPE.AUTOMATIC)" ion-button margin-top>{{ PROCESSING_TYPE.AUTOMATIC }}</button>
  </ion-col>
</ion-row>
</code>```

setProcessingType gets called when the user clicks between 'manual' and 'automatic' buttons.  type: string  is the new value that i will set to processingType.

```<code>setProcessingType(type: string): void {

this.myForm.patchValue({   // i welcome comments to correct this to 'setValue()' if needed
  processingType: type
});

let formCtrls = ['discountType', 'discountRule', 'discountAmount', 'dateRuleDays', 'dateRuleTimeStart', 'dateRuleTimeEnd'];
let add = [Validators.required];
let empty = [];

formCtrls.forEach((key, index) => {
  if (this.myForm.controls && this.myForm.controls[key]) {
    if (type === this.PROCESSING_TYPE.AUTOMATIC) {
        this.myForm.controls[key].setValidators([Validators.required]);
    } else {
      console.log('resetting validators...');
      this.myForm.controls[key].setValidators([]);
      console.log('errors on : ', key,  this.myForm.controls[key].errors);
    //  this.myForm.controls[key].markAsUntouched();     // attempt 3928
    //  this.myForm.controls[key].markAsPristine()      // attempt 3929
      //this.myForm.controls.updateValueAndValidty();   // this throws an error
    }
  }
})

  console.log('new form controls: ', this.myForm.controls);
</code>```

}

I've also subscribed to the 'processingType' valueChanges where i ran the same logic as the function above

```<code>    this.myForm.get('processingType').valueChanges.subscribe(data => this.onProcessingTypeChanged(data));
</code>```

Here are some screenshots from my logs of the values i'm trying to add a validator to:

The start (how it should be)...

After clicking 'Automatic'...why are they still null?

After clicking 'Manual'... now they are required?

Based on the above suspicion, i suspect

```<code>this.myForm.controls.updateValueAndValidty();
</code>```

or
    this.myForm.controls[key].updateValueAndValidity();

is the issue, but as I commented within the code, both of those threw 'not a function' errors.

I've googled nearly every combination of conditional validation, angular2 form model, dynamically adding validators, etc... too many links to list here, haha.

Hopefully this is enough for someone to help diagnose the problem.

Thanks in advance.

答:
UPDATE: 4/3/2017

Thanks to a comment on this post, the correct answer here is to explicitly set the errors on the control back to null.

example:

```<code>formCtrls.forEach((key, index) => {
  if (this.myForm.controls && this.myForm.controls[key]) {
    if (data === this.PROCESSING_TYPE.AUTOMATIC)
       this.myForm.controls[key].setValidators([Validators.required]);
    else {
      this.myForm.controls[key].validator = [];
      this.myForm.controls[key].setErrors(null);   // CORRECT WAY- NOW VALIDATORS ARE GONE AND ERRORS ARE NULL
    }
  }
})
</code>```

OLD answer

It seems that I fixed the issue, but am not comfortable with it. Feels like:

1.) I'm missing the obvious right way to do this.

2.) This is a huge hack.

3.) This is a bug (i highly doubt this- I usually assume I'm wrong in cases like this).

Looping through the controls and using setValidators() actually was working, I just didn't realize it until I tried @Sampath's answer above (which worked the same way as setValidators(), but didn't fix the issue).

To fix it, each time the valueChanges observer's callback was fired, I explicityly set each input's value to an empty string.

The code:

```<code>  onProcessingTypeChanged(data) {

let formCtrls = ['discountType', 'discountRule', 'discountAmount', 'dateRuleDays', 'dateRuleTimeStart', 'dateRuleTimeEnd'];
let add = [Validators.required];
let empty = [];
let newValue;

if (data === this.PROCESSING_TYPE.AUTOMATIC) newValue = "";
else newValue = " ";  // SET TO AN EMPTY STRING

this.myForm.patchValue({
    discountType: newValue,
    discountRule: newValue,
    discountAmount: newValue,
    product: newValue,
    dateRuleDays: newValue,
    dateRuleTimeStart: newValue,
    dateRuleTimeEnd: newValue,
});

formCtrls.forEach((key, index) => {
  if (this.myForm.controls && this.myForm.controls[key]) {
    if (data === this.PROCESSING_TYPE.AUTOMATIC)
       this.myForm.controls[key].setValidators([Validators.required]);
    else
      this.myForm.controls[key].setValidators([]);
  }
})
</code>```

}

After a good bit of exploring, it seems the errors (myForm.controls[key].errors) were being processed internally against this returned closure:

```<code>function(control) {
   return isEmptyInput(control.value) : { 'required': true } ? null;
}
</code>```

So, to the best of my knowledge, by not resetting each value to an empty string (which I find odd, b/c an empty string is falsy, but in the closure it passes as not being an empty input), angular registered each input as empty, and set the errors object as { required: true }, therefore registering the form as still invalid even though there was no required validators on each input.

Not going to mark this as correct- would love feedback on this if anyone corrects this logic or has similar issues.

Body:
I've been trying to use the model form in an Ionic/Angular2. I have a form that I want to do some conditional validation. The user starts with 6 fields that are required and then can choose between 'manual' and 'automatic' processing. If 'automatic' is chosen, 3 more form inputs/selects are rendered. I'd like these 3 fields to go from being not required to required.

Here's the model to start:

this.myForm = this.formBuilder.group({
  name: ['', Validators.compose([Validators.required, Validators.maxLength(45), Validators.minLength(2)])],
  img: [''],
  longDescription: ['', Validators.compose([Validators.required, Validators.maxLength(200)])],
  shortDescription: ['', Validators.compose([Validators.required, Validators.maxLength(45)])],
  processingType: [this.PROCESSING_TYPE.MANUAL],
  discountType: ['' ],
  discountRule: ['' ],
  discountAmount: ['' ],  // money, isNumbersOnly handled by custom validator
  product: [''],
  dateRuleDays: ['' ],
  dateRuleTimeStart: ['' ],
  dateRuleTimeEnd: ['' ],

  startDate: ['', Validators.required],
  expiryDate: ['', Validators.required ]
});

discountType, discountRule, discountAmount are the 3 fields that I'd like to toggle to being required.

Here's what I've tried:

markup where setProcessingType fn gets called (i can provide the full page if needed)

Processing Type

<ion-row text-center>
  <ion-col width-50>
      <button class="width-80" color="primary" (click)="setProcessingType(PROCESSING_TYPE.MANUAL)" ion-button margin-top>{{ PROCESSING_TYPE.MANUAL }}</button>
  </ion-col>
  <ion-col width-50>
      <button class="width-80" color="primary" (click)="setProcessingType(PROCESSING_TYPE.AUTOMATIC)" ion-button margin-top>{{ PROCESSING_TYPE.AUTOMATIC }}</button>
  </ion-col>
</ion-row>

setProcessingType gets called when the user clicks between 'manual' and 'automatic' buttons.  type: string  is the new value that i will set to processingType.

setProcessingType(type: string): void {

this.myForm.patchValue({   // i welcome comments to correct this to 'setValue()' if needed
  processingType: type
});

let formCtrls = ['discountType', 'discountRule', 'discountAmount', 'dateRuleDays', 'dateRuleTimeStart', 'dateRuleTimeEnd'];
let add = [Validators.required];
let empty = [];

formCtrls.forEach((key, index) => {
  if (this.myForm.controls && this.myForm.controls[key]) {
    if (type === this.PROCESSING_TYPE.AUTOMATIC) {
        this.myForm.controls[key].setValidators([Validators.required]);
    } else {
      console.log('resetting validators...');
      this.myForm.controls[key].setValidators([]);
      console.log('errors on : ', key,  this.myForm.controls[key].errors);
    //  this.myForm.controls[key].markAsUntouched();     // attempt 3928
    //  this.myForm.controls[key].markAsPristine()      // attempt 3929
      //this.myForm.controls.updateValueAndValidty();   // this throws an error
    }
  }
})

  console.log('new form controls: ', this.myForm.controls);

}

I've also subscribed to the 'processingType' valueChanges where i ran the same logic as the function above

    this.myForm.get('processingType').valueChanges.subscribe(data => this.onProcessingTypeChanged(data));

Here are some screenshots from my logs of the values i'm trying to add a validator to:

The start (how it should be)...

After clicking 'Automatic'...why are they still null?

After clicking 'Manual'... now they are required?

Based on the above suspicion, i suspect

this.myForm.controls.updateValueAndValidty();

or
    this.myForm.controls[key].updateValueAndValidity();

is the issue, but as I commented within the code, both of those threw 'not a function' errors.

I've googled nearly every combination of conditional validation, angular2 form model, dynamically adding validators, etc... too many links to list here, haha.

Hopefully this is enough for someone to help diagnose the problem.

Thanks in advance.

Body:
UPDATE: 4/3/2017

Thanks to a comment on this post, the correct answer here is to explicitly set the errors on the control back to null.

example:

formCtrls.forEach((key, index) => {
  if (this.myForm.controls && this.myForm.controls[key]) {
    if (data === this.PROCESSING_TYPE.AUTOMATIC)
       this.myForm.controls[key].setValidators([Validators.required]);
    else {
      this.myForm.controls[key].validator = [];
      this.myForm.controls[key].setErrors(null);   // CORRECT WAY- NOW VALIDATORS ARE GONE AND ERRORS ARE NULL
    }
  }
})

OLD answer

It seems that I fixed the issue, but am not comfortable with it. Feels like:

1.) I'm missing the obvious right way to do this.

2.) This is a huge hack.

3.) This is a bug (i highly doubt this- I usually assume I'm wrong in cases like this).

Looping through the controls and using setValidators() actually was working, I just didn't realize it until I tried @Sampath's answer above (which worked the same way as setValidators(), but didn't fix the issue).

To fix it, each time the valueChanges observer's callback was fired, I explicityly set each input's value to an empty string.

The code:

  onProcessingTypeChanged(data) {

let formCtrls = ['discountType', 'discountRule', 'discountAmount', 'dateRuleDays', 'dateRuleTimeStart', 'dateRuleTimeEnd'];
let add = [Validators.required];
let empty = [];
let newValue;

if (data === this.PROCESSING_TYPE.AUTOMATIC) newValue = "";
else newValue = " ";  // SET TO AN EMPTY STRING

this.myForm.patchValue({
    discountType: newValue,
    discountRule: newValue,
    discountAmount: newValue,
    product: newValue,
    dateRuleDays: newValue,
    dateRuleTimeStart: newValue,
    dateRuleTimeEnd: newValue,
});

formCtrls.forEach((key, index) => {
  if (this.myForm.controls && this.myForm.controls[key]) {
    if (data === this.PROCESSING_TYPE.AUTOMATIC)
       this.myForm.controls[key].setValidators([Validators.required]);
    else
      this.myForm.controls[key].setValidators([]);
  }
})

}

After a good bit of exploring, it seems the errors (myForm.controls[key].errors) were being processed internally against this returned closure:

function(control) {
   return isEmptyInput(control.value) : { 'required': true } ? null;
}

So, to the best of my knowledge, by not resetting each value to an empty string (which I find odd, b/c an empty string is falsy, but in the closure it passes as not being an empty input), angular registered each input as empty, and set the errors object as { required: true }, therefore registering the form as still invalid even though there was no required validators on each input.

Not going to mark this as correct- would love feedback on this if anyone corrects this logic or has similar issues.


问:
C++ Any benifits using pointer to vector of pointers?
Before I start, I have already looked at these questions:

Memory consumption of a pointer to vector of pointers

Pointer to vector vs vector of pointers vs pointer to vector of pointers

And they both do not answer my question.

I am working on a project where it involves millions of instances to work with.

The data structure I am using is a bit complicated to look at for the first time, the structure itself isn't really of any importance for this question.

Now, if I had the following:

```<code>vector<object*> *myVector;
</code>```

Everything goes to the heap.

However, what happens if I used this:

```<code>vector<object*> myVector;
</code>```

Does the vector itself get stored on the stack? And its contents are then stored on the heap? For example, if the vector had 10 million instances, would I have 10 million references on the stack for 10 million objects on the heap? Or am I missing something?

Moreover, if I used this:

```<code>vector<object> *myVector;
</code>```

Where do the contents of the vector go? Does everything go on the heap? If yes, then does it work recursively? For example:

```<code>vector<vector<vector<int>>> *myVector;
</code>```

Are all the inner vectors then stored on the heap? If yes, then it should be enough deleting myVector in the destructor, without worrying on anything else?

Anyway, I am assuming all the answers that apply to vector would also apply to unordered_map. Please tell me if I am wrong.

Thanks in advance.

答:
In general, elements of a std::vector will always be dynamically allocated on the heap. For most implementations, a std::vector<T> foo, where T could be a pointer or not, there will always be three pointers on the stack that describe the vector itself, but not the elements. For a std::vector<T> *bar, there is one pointer, bar, on stack. The three vector pointers as well as the vector elements are on the heap.

Similarly, for an std::unordered_map, the elements itself will always be dynamically allocated on the heap. Generally, any std type that has a Allocator template parameter, or any type that contains a variable amount of data, will have it's data dynamically allocated on the heap.

Now there are special cases, like custom allocators, weird optimizations, specifics of terminology, but for practical purposes, this is what you should know.

The next thing that you might want to learn about, are smart pointers, e.g. std::unique_ptr, and std::shared_ptr, ownership semantics and RAII. That is actually more important to know in order to write correct code (What do I need to delete and worry about?).

Body:
Before I start, I have already looked at these questions:

Memory consumption of a pointer to vector of pointers

Pointer to vector vs vector of pointers vs pointer to vector of pointers

And they both do not answer my question.

I am working on a project where it involves millions of instances to work with.

The data structure I am using is a bit complicated to look at for the first time, the structure itself isn't really of any importance for this question.

Now, if I had the following:

vector<object*> *myVector;

Everything goes to the heap.

However, what happens if I used this:

vector<object*> myVector;

Does the vector itself get stored on the stack? And its contents are then stored on the heap? For example, if the vector had 10 million instances, would I have 10 million references on the stack for 10 million objects on the heap? Or am I missing something?

Moreover, if I used this:

vector<object> *myVector;

Where do the contents of the vector go? Does everything go on the heap? If yes, then does it work recursively? For example:

vector<vector<vector<int>>> *myVector;

Are all the inner vectors then stored on the heap? If yes, then it should be enough deleting myVector in the destructor, without worrying on anything else?

Anyway, I am assuming all the answers that apply to vector would also apply to unordered_map. Please tell me if I am wrong.

Thanks in advance.