A constructor is a method that is automatically called when an object is created.

More C++

William J. Buchanan BSc, CEng, PhD, in Software Development for Engineers, 1997

12.1 Constructors and destructors

A constructor allows for the initialization of a class and a destructor allows the class function to be removed from memory. They are defined as follows:

A constructor is a special initialization function that is automatically called whenever a class is declared. The constructor always has the same name as the class name, and no data types are defined for the argument list or the return type. Normally a constructor is used to initialize a class.

A destructor is a member of a function which is automatically called when the class is destroyed. It has the same name as the class name but is preceded by a tilde (~). Normally a destructor is used to clean-up when the class is destroyed.

C++ Program 12.1 has a class which is named class_ex. The constructor for this class is class_ex() and the destructor is ~class_ex(). Test run 12.1 shows a sample run. It can be seen that initially when the program is run the message Constructing is displayed. This is because the class is initially declared to c1. Then when the function test() is called the Constructing message is again displayed as a new class is defined (c2). When the program leaves this function the destructor is called and thus the message Destructor is displayed. Finally, when the program quits the destructor is again called.

A constructor is a method that is automatically called when an object is created.

A constructor is a method that is automatically called when an object is created.

A constructor is a method that is automatically called when an object is created.

Read full chapter

URL: https://www.sciencedirect.com/science/article/pii/B9780340700143500578

Light Sources

Matt Pharr, ... Greg Humphreys, in Physically Based Rendering (Third Edition), 2017

12.6 Infinite area lights

Another useful kind of light is the infinite area light—an infinitely far away area light source that surrounds the entire scene. One way to visualize this light is as an enormous sphere that casts light into the scene from every direction. One important use of infinite area lights is for environment lighting, where an image that represents illumination in an environment is used to illuminate synthetic objects as if they were in that environment. Figures 12.19 and 12.20 compare illuminating a car model with a standard area light to illuminating it with environment maps that simulate illumination from the sky at a few different times of day (the illumination maps used are shown in Figure 12.21). The increase in realism is striking. The InfiniteAreaLight class is implemented in lights/infinite.h and lights/infinite.cpp.

A constructor is a method that is automatically called when an object is created.

Figure 12.19. Car model (a) illuminated with an area light and a directional light and (b) illuminated with morning skylight from an environment map. Using a realistic distribution of illumination gives an image that is much more visually compelling. In particular, with illumination arriving from all directions, the glossy reflective properties of the paint are much more visually apparent.

(Model courtesy of Yasutoshi Mori.)

A constructor is a method that is automatically called when an object is created.

Figure 12.20. Changing just the environment map used for illumination gives quite different results in the final image: (a) using a midday skylight distribution and (b) using a sunset environment map.

(Model courtesy of Yasutoshi Mori.)

A constructor is a method that is automatically called when an object is created.

Figure 12.21. Environment Maps Used for Illumination in Figures 12.19 and 12.20. (a) Morning, (b) midday, and (c) sunset sky. (The bottom halves of these maps aren’t shown here, since they are just black pixels.)

A widely used representation for light for this application is the latitude–longitude radiance map. (This representation is also known as the equirectangular projection.) The EnvironmentCamera can be used to create image maps for the light, or see the “Further Reading” section for information about techniques for capturing this lighting data from real-world environments.

〈InfiniteAreaLight Declarations〉 ≡

 class InfiniteAreaLight : public Light {

 public:

 〈InfiniteAreaLight Public Methods 740

 private:

 〈InfiniteAreaLight Private Data 740

 };

EnvironmentCamera 376

InfiniteAreaLight 737

Light 714

Like the other lights, the InfiniteAreaLight takes a transformation matrix; here, its use is to orient the image map. It then uses spherical coordinates to map from directions on the sphere to (θ, ϕ) directions, and from there to (u, v) texture coordinates. The provided transformation thus determines which direction is “up.”

The constructor loads the image data from the disk and creates a MIPMap to store it. The fragment that loads the data, 〈Read texel data from texmap and initialize Lmap〉, is straightforward and won’t be included here. The other code fragment in the constructor, 〈Initialize sampling PDFs for infinite area light〉, is related to Monte Carlo sampling of InfiniteAreaLights and will be defined later, in Section 14.2.4.

InfiniteAreaLight 737

MIPMap 625

As with DistantLights, because the light is defined as being infinitely far away, the MediumInterface for an infinite area light must have nullptr values for its Medium *s, corresponding to a vacuum.

DistantLight 731

InfiniteAreaLight 737

Light 714

LightFlags::Infinite 715

MediumInterface 684

Spectrum 315

Transform 83

〈InfiniteAreaLight Method Definitions〉 ≡

 InfiniteAreaLight::InfiniteAreaLight(const Transform &LightToWorld,

 const Spectrum &L, int nSamples, const std::string &texmap)

 : Light((int)LightFlags::Infinite, LightToWorld,

 MediumInterface(), nSamples) {

 〈Read texel data from texmap and initialize Lmap

 〈Initialize sampling PDFs for infinite area light 847

 }

〈InfiniteAreaLight Private Data〉 ≡  737

 std::unique_ptr < MIPMap < RGBSpectrum > > Lmap;

Like DistantLights, InfiniteAreaLights also need the scene bounds; here again, the Preprocess() method finds the scene bounds after all of the scene geometry has been created.

〈InfiniteAreaLight Public Methods〉 ≡  737

 void Preprocess(const Scene &scene) {

 scene.WorldBound().BoundingSphere(&worldCenter, &worldRadius);

 }

〈InfiniteAreaLight Private Data〉 + ≡ 737

 Point3f worldCenter;

 Float worldRadius;

Bounds3::BoundingSphere() 81

DistantLight 731

Float 1062

InfiniteAreaLight::worldCenter 740

InfiniteAreaLight::worldRadius 740

MIPMap 625

Point3f 68

RGBSpectrum 332

Scene 23

Scene::WorldBound() 24

Because InfiniteAreaLights cast light from all directions, it’s also necessary to use Monte Carlo integration to sample their illumination. Therefore, the InfiniteAreaLight::Sample_Li() method will be defined in Section 14.2.

Like directional lights, the total power from the infinite area light is related to the surface area of the scene. Like many other lights in this chapter, the power computed here is approximate; here, all texels are given equal weight, which ignores the fact that with an equirectangular projection, the differential solid angle subtended by each pixel values with its θ value (Section 14.2.4).

〈InfiniteAreaLight Method Definitions〉 + ≡

 Spectrum InfiniteAreaLight::Power() const {

 return Pi * worldRadius * worldRadius *

 Spectrum(Lmap- > Lookup(Point2f(.5f, .5f), .5f),

 SpectrumType::Illuminant);

 }

Because infinite area lights need to be able to contribute radiance to rays that don’t hit any geometry in the scene, we’ll add a method to the base Light class that returns emitted radiance due to that light along a ray that escapes the scene bounds. (The default implementation for other lights returns no radiance.) It is the responsibility of the integrators to call this method for these rays.

〈Light Method Definitions〉 + ≡

 Spectrum Light::Le(const RayDifferential &ray) const {

 return Spectrum(0.f);

 }

InfiniteAreaLight 737

InfiniteAreaLight::Lmap 740

InfiniteAreaLight::Sample_Li() 849

InfiniteAreaLight::worldRadius 740

Inv2Pi 1063

InvPi 1063

Light 714

Light::WorldToLight 715

MIPMap::Lookup() 635

Pi 1063

Point2f 68

Ray::d 73

RayDifferential 75

Spectrum 315

SpectrumType::Illuminant 330

SphericalPhi() 346

SphericalTheta() 346

Vector3::Normalize() 66

Vector3f 60

〈InfiniteAreaLight Method Definitions〉 + ≡

 Spectrum InfiniteAreaLight::Le(const RayDifferential &ray) const {

 Vector3f w = Normalize(WorldToLight(ray.d));

 Point2f st(SphericalPhi(w) * Inv2Pi,

 SphericalTheta(w) * InvPi);

 return Spectrum(Lmap- > Lookup(st), SpectrumType::Illuminant);

 }

Read full chapter

URL: https://www.sciencedirect.com/science/article/pii/B9780128006450500129

Data Abstraction and Object Orientation

Michael L. Scott, in Programming Language Pragmatics (Third Edition), 2009

9.3.1 Choosing a Constructor

Example 9.22

Naming Constructors in Eiffel

Smalltalk, Eiffel, C++, Java, and C# all allow the programmar to specify more than one constructor for a given class. In C++, Java, and C#, the constructors behave like overloaded subroutines: they must be distinguished by their numbers and types of arguments. In Smalltalk and Eiffel, different constructors can have different names; code that creates an object must name a constructor explicitly. In Eiffel one might say

class COMPLEX

creation

 new_cartesian, new_polar

feature {ANY}

 x, y : REAL

 new_cartesian(x_val, y_val : REAL) is

 do

 x := x_val; y := y_val

 end

 new_polar(rho, theta : REAL) is

 do

 x := rho * cos(theta)

 y := rho * sin(theta)

 end

 -- other public methods

feature {NONE}

 -- private methods

end -- class COMPLEX

a, b : COMPLEX

!!b.new_cartesian(0, 1)

!!a.new_polar(pi/2, 1)

The !! operator is Eiffel's equivalent of new. Because class COMPLEX specified constructor (“creator”) methods, the compiler will insist that every use of !! specify a constructor name and arguments. There is no straightforward analog of this code in C++; the fact that both constructors take two real arguments means that they could not be distinguished by overloading.

Smalltalk resembles Eiffel in the use of multiple named constructors, but it distinguishes more sharply between operations that pertain to an individual object and operations that pertain to a class of objects. Smalltalk also adopts an anthropomorphic programming model in which every operation is seen as being executed by some specific object in response to a request (a “message”) from some other object. Since it makes little sense for an object O to create itself, O must be created by some other object (call it C) that represents O's class. Of course, because C is an object, it must itself belong to some class. The result of this reasoning is a system in which each class definition really introduces a pair of classes and a pair of objects to represent them. Objective-C and CLOS have similar dual hierarchies.

Example 9.23

Metaclasses in Smalltalk

Consider, for example, the standard class named Date. Corresponding to Date is a single object (call it D) that performs operations on behalf of the class. In particular, it is D that creates new objects of class Date. Because only objects execute operations (classes don't), we don't really need a name for D; we can simply use the name of the class it represents:

todaysDate <- Date today

This code causes D to execute the today constructor of class Date, and assigns a reference to the newly created object into a variable named todaysDate.

So what is the class of D ? It clearly isn't Date, because D represents class Date. Smalltalk says that D is an object (in fact the only object) of the metaclass Date class. For technical reasons, it is also necessary for Date class to be represented by an object. To avoid an infinite regression, all objects that represent metaclasses are instances of a single class named Metaclass.

Modula-3 and Oberon provide no constructors at all: the programmar must initialize everything explicitly. Ada 95 supports constructors and destructors (called Initialize and Finalize routines) only for objects of types derived from the standard library type Controlled.

Read full chapter

URL: https://www.sciencedirect.com/science/article/pii/B9780123745149000197

Functional Modeling with OCL Contracts

Raul Sidnei Wazlawick, in Object-Oriented Analysis and Design for Information Systems, 2014

8.4 Query return

As mentioned before, system commands change data while queries just return data to the user. The contracts for system queries must define what is returned, and this can be done in OCL by using the body clause.

Expressions that represent preconditions are all Boolean, but expressions that represent the return of a query may have other types. They can return strings, numbers, lists, tuples, or even more complex structures. The following examples are based on the model of Figure 8.1. Initially, a query is defined that returns the total of a given cart:

Context Livir::getCartTotal(aCartId:CartId):Money

 body:

  cart[aCartId].total

System queries as well as system commands always have the Controller as their context. Therefore, in the example above, cart is a property of the controller Livir: an association role from it to the class Cart.

The following query returns the name and birthdate of a given customer:

Context

 Livir::getCustomerNameBirthDate(aCustomerId:CustomerId):Tuple

 body:

  Tuple {

   name=customer[aCustomerId].name,

   birthDate=customer[aCustomerId].birthDate

  }

The Tuple constructor is one of the ways to represent DTOs4 in OCL; the tuple works as a Pascal record in the example with two fields: name and birthDate. The values of the fields are defined by the expressions after the “=”.

To avoid repeating expressions like customer[aCustomerId] or even more complex expressions, the def clause can be used in order to define a constant that refers to the original expression. Using the def clause, the contract above would look like the following:

Context

 Livir::getCustomerNameBirthDate(aCustomerId:CustomerId):Tuple

 def:

  aCustomer=customer[aCustomerId]

 body:

  Tuple {

   name=aCustomer.name,

   birthDate=aCustomer.birthDate

  }

The expression inside the def clause indicates that the identifier aCustomer is referring to the customer whose ID is the parameter aCustomerId received from the query.

The following expression makes a projection in the set of customers returning the names of all customers:

Context Livir::listCustomerNames():Set

 body:

  customer.name

The next expression applies a filter and a projection, returning the names of all customers that are less than 25 years old:

Context Livir::listYoungCustomers():Set

 body:

  customer->select(birthDate.addYear(25)>Date.getCurrent()).name

The idea in the example above is to add 25 years to the birthdate of the customer and compare it with the current date: if the customer reaches her 25th birthday after the current date then she is younger than 25 years. OCL also has operations to add days and months to dates: addDay and addMonth, respectively. The expression Date.currentDate returns the system’s current date.

The last example is a query that returns the cart summary, as shown in Figure 8.2.

Context Livir::getCartSummary(aCartId:CartId):Tuple

 def: aCart=cart[aCartId]

 body:

  Tuple {

   total=aCart.total,

   items=aCart.item->collect(anItem|

    Tuple {

     title=anItem.book.title,

     authorsName=anItem.book.authorsName,

     quantity=anItem.quantity,

     unitPrice=anItem.unitPrice,

     subtotal=anItem.subtotal

    }

   )

  }

The collect expression is a way to obtain a set whose elements are properties or transformations on properties of another set. The dot notation (“.”) itself is an abbreviated form of collect. For example, customer.name is equivalent to customer->collect(aCustomer|aCustomer.name) or customer->collect(name).

When possible, the dot notation is preferred because it is shorter. But in the getCartSummary example, the need to create a tuple instead of accessing a property of the elements of a set prevents the use of the dot, because the Tuple operator is prefixed. Thus, the collect expression has to be explicitly used in that case.

In the example, two tuple structures were built: the outer one contains the total of the cart and the ordered set of its items; the inner one contains for each item the information that is needed as mentioned in Figure 8.2: book title, author’s name, etc.

Read full chapter

URL: https://www.sciencedirect.com/science/article/pii/B9780124186736000089

Scripting Languages

Michael L. Scott, in Programming Language Pragmatics (Third Edition), 2009

Python and Ruby

As we have noted, both Python and Ruby are explicitly object-oriented. Both employ a uniform reference model for variables. Like Smalltalk, both incorporate an object hierarchy in which classes themselves are represented by objects. The root class in Python is called object; in Ruby it is Object.

Example 13.81

Constructors in Python and Ruby

In both Python and Ruby, each class has a single distinguished constructor, which cannot be overloaded. In Python it is __init__; in Ruby it is initialize. To create a new object in Python one says my_object = My_class(args); in Ruby one says my_object = My_class.new(args). In each case the args are passed to the constructor. To achieve the effect of overloading, with different numbers or types of arguments, one must arrange for the single constructor to inspect its arguments explicitly. We employed a similar idiom in Perl (in the new routine of Figure 13.21) and JavaScript (in the Integer function of Figure 13.22).

Both Python and Ruby are more flexible than PHP or more traditional object-oriented languages regarding the contents (members) of a class. New fields can be added to a Python object simply by assigning to them: my_object.new_field = value. The set of methods, however, is fixed when the class is first defined. In Ruby only methods are visible outside a class (“put” and “get” methods must be used to access fields), and all methods must be explicitly declared. It is possible, however, to modify an existing class declaration, adding or overriding methods. One can even do this on an object-by-object basis. As a result, two objects of the same class may not display the same behavior.

Example 13.82

Naming Class Members in Python and Ruby

Python and Ruby differ in many other ways. The initial parameter to methods is explicit in Python; by convention it is usually named self. In Ruby self is a keyword, and the parameter it represents is invisible. Any variable beginning with a single @ sign in Ruby is a field of the current object. Within a Python method, uses of object members must name the object explicitly. One must, for example, write self.print(); just print() will not suffice.

Design & Implementation

Executable class declarations

Both Python and Ruby take the interesting position that class declarations are executable code. Elaboration of a declaration executes the code inside. Among other things, we can use this mechanism to achieve the effect of conditional compilation:

class My_class # Ruby code

 def initialize(a, b)

 @a = a; @b = b;

 end

 if expensive_function()

 def get()

 return @a

 end

 else

 def get()

 return @b

 end

 end

end

Instead of computing the expensive function inside get, on every invocation, we compute it once, ahead of time, and define an appropriate specialized version of get.

Ruby methods may be public, protected, or private.11 Access control in Python is purely a matter of convention; both methods and fields are universally accessible. Finally, Python has multiple inheritance. Ruby has mix-in inheritance: a class cannot obtain data from more than one ancestor. Unlike most other languages, however, Ruby allows an interface (mix-in) to define not only the signatures of methods, but also their implementation (code).

Check Your Understanding

44.

Contrast the philosophies of Perl and Ruby with regard to error checking and reporting.

45.

Compare the numeric types of popular scripting languages to those of compiled languages like C or Fortran.

46.

What are bignums? Which languages support them?

47.

What are associative arrays? By what other names are they sometimes known?

48.

Why don't most scripting languages provide direct support for records?

49.

What is a typeglob in Perl? What purpose does it serve?

50.

Describe the tuple and set types of Python.

51.

Explain the unification of arrays and hashes in PHP and Tcl.

52.

Explain the unification of arrays and objects in JavaScript.

53.

Explain how tuples and hashes can be used to emulate multidimensional arrays in Python.

54.

Explain the concept of context in Perl. How is it related to type compatibility and type inference? What are the two principal contexts defined by the language's operators?

55.

Compare the approaches to object orientation taken by Perl 5, PHP 5, JavaScript, Python, and Ruby.

56.

What is meant by the blessing of a reference in Perl?

57.

What are prototypes in JavaScript? What purpose do they serve?

Read full chapter

URL: https://www.sciencedirect.com/science/article/pii/B9780123745149000239

OpenMP

Victor Alessandrini, in Shared Memory Application Programming, 2016

Constructing the directed acyclic graph

Figure 10.10 shows the construction of the directed acyclic graph, which proceeds as follows:

A constructor is a method that is automatically called when an object is created.

Figure 10.10. Constructing a directed acyclic graph.

The constructor Graph G creates a graph. It defines internally an empty STL vector of cells.

The member function G.create_random_dag(N) starts by allocating an STL vector of cells of size N. Then, successive vector elements are visited. For each vector element, the number of ancestors is randomly selected. If there are ancestors, they are again randomly chosen among the preceding vector elements. Then, the cell is initialized (ref_count, input pointers) and, in the ancestor cells, a pointer to the current cell is added to the successors vector. At this point, the graph is constructed. It follows from this procedure that the number of ancestors is limited to 2, but the number of successors is arbitrary.

G.get_root_set(std::vector<Cell*> root_set) is another useful function. It receives as argument a reference to an empty STL vector of cell pointers. It fills this vector with the addresses of the root cells, namely, cells that have no ancestors. Obviously, cells with no ancestors are the starting point of the graph traversal algorithm.

Read full chapter

URL: https://www.sciencedirect.com/science/article/pii/B9780128037614000101

C++ Usage

Martin Reddy, in API Design for C++, 2011

6.2.2 Defining Constructors and Assignment

Because writing constructors and operators can be a tricky business, here's an example that demonstrates the various combinations. It builds on the previous array example and presents a class for storing an array of strings. Because the array is allocated dynamically, you must define a copy constructor and assignment operator, otherwise the memory will be freed twice on destruction if you copy the array. Here's the declaration of the Array class in the header file:

#include <string>

class Array

{

public:

// default constructor

Array();

// non-default constructor

explicit Array(int size);

// destructor

~Array();

// copy constructor

Array(const Array &in_array);

// assignment operator

Array &operator = (const Array &in_array);

std::string Get(int index) const;

bool Set(int index, const std::string &str);

int GetSize() const;

private:

int mSize;

std::string *mArray;

};

and here are sample definitions for the constructors and assignment operator:

#include "array.h"

#include <algorithm>

// default constructor

Array::Array() :

mSize(0),

mArray(NULL)

{

}

// non-default constructor

Array::Array(int size) :

mSize(size),

mArray(new std::string[size])

{

}

// destructor

Array::~Array()

{

delete [] mArray;

}

// copy constructor

Array::Array(const Array &in_array) :

mSize(in_array.mSize),

mArray(new std::string[in_array.mSize])

{

std::copy(in_array.mArray, in_array.mArray + mSize, mArray);

}

// assignment operator

Array &Array::operator = (const Array &in_array)

{

if (this != &in_array) // check for self assignment

{

delete [] mArray; // delete current array first

mSize = in_array.mSize;

mArray = new std::string[in_array.mSize];

std::copy(in_array.mArray, in_array.mArray + mSize, mArray);

}

return *this;

}

Given the aforementioned Array class, the following code demonstrates when the various methods will be called.

Array a; // default constructor

Array a(10); // non-default constructor

Array b(a); // copy constructor

Array c = a; // copy constructor (because c does not exist yet)

b = c; // assignment operator

Note that there are certain cases where your compiler may elide the call to your copy constructor, for example, if it performs some form of Return Value Optimization (Meyers, 1998).

Read full chapter

URL: https://www.sciencedirect.com/science/article/pii/B9780123850034000063

Object-Oriented Programming

Raymond Greenlaw, Y. Daniel Liang, in Encyclopedia of Information Systems, 2003

II.A. Creating Objects and Object Reference Variables

Objects are created through constructors. A constructor has exactly the same name as its defining class. Constructors are a special kind of method. Like methods, constructors can be overloaded, making it easier to develop objects with different initial data values. Constructors play the role of initializing objects. A constructor with no parameters is referred to as a default constructor. If a class does not define any constructors explicitly (the case in Listing 1), a default constructor is assumed implicitly. If a class defines constructors explicitly, a default constructor will not exist unless it is defined explicitly. Listing 2 expands the Person class defined in Listing 1 with two constructors. Listing 2: Class definition for Person with constructors.

A constructor is a method that is automatically called when an object is created.

Objects are created using the new operator on a constructor as follows:

A constructor is a method that is automatically called when an object is created.

For example, new Person () creates an object of the Person class. Newly created objects are allocated in memory. Objects are accessed via object reference variables to the objects. Such reference variables are declared using the following syntax:

A constructor is a method that is automatically called when an object is created.

The types of reference variables are known as reference types. The following statement declares the variable p to be of the Person type:

A constructor is a method that is automatically called when an object is created.

The variable p can reference a Person object. The following statement creates an object and assigns its reference to p.

A constructor is a method that is automatically called when an object is created.

You can combine the declaration of an object reference variable, creation of an object, and assignment of the object reference to the variable together in one statement using the following syntax:

A constructor is a method that is automatically called when an object is created.

Below is a concrete example of this syntax:

A constructor is a method that is automatically called when an object is created.

The variable p now holds a reference to a Person object.

When a variable of a reference type is declared, the variable holds a special value, null, which means that the variable does not reference any object. Once an object is created, its reference can be assigned to a variable. For example, the statement

A constructor is a method that is automatically called when an object is created.

creates a Person object by allocating the memory space for the object and assigns its memory reference to the variable p. When you assign one variable into another, the other variable is set to the same value.

After an object is created, its data can be accessed and its methods can be invoked using the following dot notation:

A constructor is a method that is automatically called when an object is created.

For example, p.setName (“Sam J Fox”) invokes the setName method of object p. Methods are invoked as operations on objects. If the address property were defined as public, the variable address could be accessed using p.address.

Read full chapter

URL: https://www.sciencedirect.com/science/article/pii/B0122272404001246

Materials

Matt Pharr, ... Greg Humphreys, in Physically Based Rendering (Third Edition), 2017

9.1 BSDFs

The BSDF class represents a collection of BRDFs and BTDFs. Grouping them in this manner allows the rest of the system to work with composite BSDFs directly, rather than having to consider all of the components they may have been built from. Equally important, the BSDF class hides some of the details of shading normals from the rest of the system. Shading normals, either from per-vertex normals in triangle meshes or from bump mapping, can substantially improve the visual richness of rendered scenes, but because they are an ad hoc construct, they are tricky to incorporate into a physically based renderer. The issues that they introduce are handled in the BSDF implementation.

〈BSDF Declarations〉 + ≡

 class BSDF {

 public:

 〈BSDF Public Methods 573

 〈BSDF Public Data 573

 private:

 〈BSDF Private Methods 576

 〈BSDF Private Data 573

 };

The BSDF constructor takes a SurfaceInteraction object that contains information about the differential geometry at the point on a surface as well as a parameter eta that gives the relative index of refraction over the boundary. For opaque surfaces, eta isn’t used, and a value of one should be provided by the caller. (The default value of one for eta is for just this case.) The constructor computes an orthonormal coordinate system with the shading normal as one of the axes; this coordinate system will be useful for transforming directions to and from the BxDF coordinate system that is described in Figure 8.2. Throughout this section, we will use the convention that ns denotes the shading normal and ng the geometric normal (Figure 9.1).

A constructor is a method that is automatically called when an object is created.

Figure 9.1. The geometric normal, ng, defined by the surface geometry, and the shading normal, ns, given by per-vertex normals and/or bump mapping, will generally define different hemispheres for integrating incident illumination to compute surface reflection. This inconsistency is important to handle carefully since it can otherwise lead to artifacts in images.

BSDF 572

BxDF 513

SurfaceInteraction 116

〈BSDF Public Methods〉 ≡  572

 BSDF(const SurfaceInteraction &si, Float eta = 1)

 : eta(eta), ns(si.shading.n), ng(si.n),

 ss(Normalize(si.shading.dpdu)), ts(Cross(ns, ss)) { }

〈BSDF Public Data〉 ≡  572

 const Float eta;

〈BSDF Private Data〉 ≡  572

 const Normal3f ns, ng;

 const Vector3f ss, ts;

The BSDF implementation stores only a limited number of individual BxDF components. It could easily be extended to allocate more space if more components were given to it, although this isn’t necessary for any of the Material implementations in pbrt thus far, and the current limit of eight is plenty for almost all practical applications.

〈BSDF Public Methods〉 + ≡ 572

 void Add(BxDF *b) {

 Assert(nBxDFs < MaxBxDFs);

 bxdfs[nBxDFs++] = b;

 }

〈BSDF Private Data〉 + ≡ 572

 int nBxDFs = 0;

 static constexpr int MaxBxDFs = 8;

 BxDF *bxdfs[MaxBxDFs];

For other parts of the system that need additional information about the particular BRDFs and BTDFs that are present, a method returns the number of BxDFs stored by the BSDF that match a particular set of BxDFType flags.

〈BSDF Public Methods〉 + ≡ 572

 int NumComponents(BxDFType flags = BSDF_ALL) const;

The BSDF also has methods that perform transformations to and from the local coordinate system used by BxDFs. Recall that, in this coordinate system, the surface normal is along the z axis (0, 0, 1), the primary tangent is (1, 0, 0), and the secondary tangent is (0, 1, 0). The transformation of directions into “shading space” simplifies many of the BxDF implementations in Chapter 8. Given three orthonormal vectors s, t, and n in world space, the matrix M that transforms vectors in world space to the local reflection space is

M=sxsy sztxtytznxnynz =stn .

Assert() 1069

BSDF 572

BSDF::bxdfs 573

BSDF::nBxDFs 573

BSDF_ALL 513

BxDF 513

BxDFType 513

Cross() 65

Float 1062

Material 577

Normal3f 71

SurfaceInteraction 116

Vector3::Normalize() 66

Vector3f 60

To confirm this yourself, consider, for example, the value of M times the surface normal n, Mn = (s • n, t • n, n • n). Since s, t, and n are all orthonormal, the x and y components of Mn are zero. Since n is normalized, n • n = 1. Thus, Mn = (0, 0, 1), as expected.

In this case, we don’t need to compute the inverse transpose of M to transform normals (recall the discussion of transforming normals in Section 2.8.3). Because M is an orthogonal matrix (its rows and columns are mutually orthogonal), its inverse is equal to its transpose, so it is its own inverse transpose already.

〈BSDF Public Methods〉 + ≡ 572

 Vector3f WorldToLocal(const Vector3f &v) const {

 return Vector3f(Dot(v, ss), Dot(v, ts), Dot(v, ns));

 }

The method that takes vectors back from local space to world space transposes M to find its inverse before doing the appropriate dot products.

〈BSDF Public Methods〉 + ≡ 572

 Vector3f LocalToWorld(const Vector3f &v) const {

 return Vector3f(ss.x * v.x + ts.x * v.y + ns.x * v.z,

 ss.y * v.x + ts.y * v.y + ns.y * v.z,

 ss.z * v.x + ts.z * v.y + ns.z * v.z);

 }

Shading normals can cause a variety of undesirable artifacts in practice (Figure 9.2). Figure 9.2(a) shows a light leak: the geometric normal indicates that ωi and ωo lie on opposite sides of the surface, so if the surface is not transmissive, the light should have no contribution. However, if we directly evaluate the scattering equation, Equation (5.9), about the hemisphere centered around the shading normal, we will incorrectly incorporate the light from ωi. This case demonstrates that ns can’t just be used as a direct replacement for ng in rendering computations.

A constructor is a method that is automatically called when an object is created.

Figure 9.2. The Two Types of Errors That Result from Using Shading Normals. (a) A light leak: the geometric normal indicates that the light is on the back side of the surface, but the shading normal indicates the light is visible (assuming a reflective and not transmissive surface). (b) A dark spot: the geometric normal indicates that the surface is illuminated, but the shading normal indicates that the viewer is behind the lit side of the surface.

BSDF::ns 573

BSDF::ss 573

BSDF::ts 573

Dot() 63

Vector3f 60

Figure 9.2(b) shows a similar tricky situation: the shading normal indicates that no light should be reflected to the viewer, since it is not in the same hemisphere as the illumination, while the geometric normal indicates that they are in the same hemisphere. Direct use of ns would cause ugly black spots on the surface where this situation happens.

Fortunately, there is an elegant solution to these problems. When evaluating the BSDF, we can use the geometric normal to decide if we should be evaluating reflection or transmission: if ωi and ωo lie in the same hemisphere with respect to ng, we evaluate the BRDFs, and otherwise we evaluate the BTDFs. In evaluating the scattering equation, however, the dot product of the normal and the incident direction is still taken with the shading normal rather than the geometric normal.

Now it should be clear why pbrt requires BxDFs to evaluate their values without regard to whether ωi and ωo are in the same or different hemispheres. This convention means that light leaks are avoided, since we will only evaluate the BTDFs for the situation in Figure 9.2(a), giving no reflection for a purely reflective surface. Similarly, black spots are avoided since we will evaluate the BRDFs for the situation in Figure 9.2(b), even though the shading normal would suggest that the directions are in different hemispheres.

Given these conventions, the method that evaluates the BSDF for a given pair of directions follows directly. It starts by transforming the world space direction vectors to local BSDF space and then determines whether it should use the BRDFs or the BTDFs. It then loops over the appropriate set and evaluates the sum of their contributions.

〈BSDF Method Definitions〉 ≡

 Spectrum BSDF::f(const Vector3f &woW, const Vector3f &wiW,

 BxDFType flags) const {

 Vector3f wi = WorldToLocal(wiW), wo = WorldToLocal(woW);

 bool reflect = Dot(wiW, ng) * Dot(woW, ng) > 0;

 Spectrum f(0.f);

 for (int i = 0; i < nBxDFs; ++i)

 if (bxdfs[i]- > MatchesFlags(flags) &&

 ((reflect && (bxdfs[i]- > type & BSDF_REFLECTION)) ∥

 (!reflect && (bxdfs[i]- > type & BSDF_TRANSMISSION))))

 f + = bxdfs[i]- > f(wo, wi);

 return f;

 }

pbrt also provides BSDF methods that return the BSDF’s reflectances. (Recall the definition of reflectance in Section 8.1.1.) The two corresponding methods just loop over the BxDFs and sum the values returned by their BxDF::rho() methods; their straightforward implementations aren’t included here. These methods take arrays of samples for BxDFs for use in Monte Carlo sampling algorithms if needed (recall the BxDF::rho() interface defined in Section 8.1.1, which takes such samples as well.)

BSDF 572

BSDF::bxdfs 573

BSDF::nBxDFs 573

BSDF::WorldToLocal() 574

BSDF_ALL 513

BSDF_REFLECTION 513

BSDF_TRANSMISSION 513

BxDF 513

BxDF::f() 514

BxDF::MatchesFlags() 513

BxDF::rho() 515

BxDFType 513

Dot() 63

Point2f 68

Spectrum 315

Vector3f 60

〈BSDF Public Methods〉 + ≡ 572

 Spectrum rho(int nSamples, const Point2f *samples1,

 const Point2f *samples2, BxDFType flags = BSDF_ALL) const;

 Spectrum rho(const Vector3f &wo, int nSamples, const Point2f *samples,

 BxDFType flags = BSDF_ALL) const;

9.1.1 BSDF Memory management

For each ray that intersects geometry in the scene, one or more BSDF objects will be created by the Integrator in the process of computing the radiance carried along the ray. (Integrators that account for multiple interreflections of light will generally create a number of BSDFs along the way.) Each of these BSDFs in turn has a number of BxDFs stored inside it, as created by the Materials at the intersection points.

A naïve implementation would use new and delete to dynamically allocate storage for both the BSDF as well as each of the BxDFs that it holds. Unfortunately, such an approach would be unacceptably inefficient—too much time would be spent in the dynamic memory management routines for a series of small memory allocations. Instead, the implementation here uses a specialized allocation scheme based on the MemoryArena class described in Section A.4.3.1 A MemoryArena is passed into methods that allocate memory for BSDFs. For example, the SamplerIntegrator::Render() method creates a MemoryArena for each image tile and passes it to the integrators, which in turn pass it to the Material.

For the convenience of code that allocates BSDFs and BxDFs (e.g., the Materials in this chapter), there is a macro that hides some of the messiness of using the memory arena. Instead of using the new operator to allocate those objects like this:

 BSDF *b = new BSDF;

 BxDF *lam = new LambertianReflection(Spectrum(0.5f));

code should instead be written with the ARENA_ALLOC() macro, like this:

 BSDF *b = ARENA_ALLOC(arena, BSDF);

 BxDF *lam = ARENA_ALLOC(arena, LambertianReflection)(Spectrum(0.5f));

where arena is a MemoryArena.

The ARENA_ALLOC() macro uses the placement operator new to run the constructor for the object at the returned memory location.

〈Memory Declarations〉 ≡

 #define ARENA_ALLOC(arena, Type) new (arena.Alloc(sizeof(Type))) Type

The BSDF destructor is a private method in order to ensure that it isn’t inadvertently called (e.g., due to an attempt to delete a BSDF). Making the destructor private ensures a compile time error if it is called. Trying to delete memory allocated by the MemoryArena could lead to errors or crashes, since a pointer to the middle of memory managed by the MemoryArena would be passed to the system’s dynamic memory freeing routine.

In turn, an implication of the allocation scheme here is that BSDF and BxDF destructors are never executed. This isn’t a problem for the ones currently implemented in the system.

〈BSDF Private Methods〉 ≡  572

 ~ BSDF() { }

ARENA_ALLOC() 576

BSDF 572

BxDF 513

Integrator 25

Material 577

MemoryArena 1074

MemoryArena::Alloc() 1074

MemoryArena::Reset() 1076

SamplerIntegrator::Render() 26

Read full chapter

URL: https://www.sciencedirect.com/science/article/pii/B9780128006450500099

Java Sockets

James C. Foster, Mike Price, in Sockets, Shellcode, Porting, & Coding, 2005

TCP clients

TCP client socket programming is simple using the java.net package. A single class (Socket) is used to create and manage the details of new TCP connections. Data is transferred to and from the socket using the standard InputStream and OutputStream classes located in the java, io package.

The Socket class provides several constructors and methods useful for establishment, control, and termination of TCP connections. The constructors are used to define and establish new connections. The remaining methods are used to send and receive data, retrieve information on established connections, fine-tune various aspects of data transfer, determine connection state, and for connection termination.

Of these constructors and methods, only a few are required to implement basic TCP client socket functionality (see Example 5.1).

A constructor is a method that is automatically called when an object is created.
Example 5.1

TCP Client Socket (TCPClientl.java)

1 /*

2 * TCPClient1.java

3 *

4 * TCP client socket program to connect, request

5 * and receive data using TCP and HTTP 1.0

6 * protocols.

7 *

8 * Usage :

9 *

10 * java TCPClientl <target_ip> <target_port> <resource>

11 *

12 *

13 */

14 import java.io.* ;

15 import j ava.net.* ;

16

17 public class TCPClientl

18 {

19 public static void main(String[] args)

20 {

21 InputStream is = null ;

22 OutputStream os = null;

23 Socket sock = null;

24 String addr = null;

25 String res = null;

26 String send = null;

27 String tmp = null ;

28 byte[] recv = new byte[4096];

29 int port = 0;

30 int len = 0;

31

32 if(args.length != 3)

33 {

34 System.err.println(“usage: java TCPClientl” +

35 “ <target_ip> <target_port>“ +

36 “ <resource>.”);

37

38 System.err.println(“Example: java TCPClientl” +

39 “127.0.0.1 80 /”);

40

41 System.exit(1);

42 }

43

44 addr = args [0];

45 tmp = args [1];

46 res = args[2];

47

48 try

49 {

50 // convert port value to integer

51 port = Integer.parselnt(tmp);

52

53 // connect to IP address and port

54 sock = new Socket(addr, port);

55

56 // get connection input & output streams

57 is = sock.getInputStream ();

58 os = sock.getOutputStream();

59

60 // no exception thrown, connection established

61 send = “GET “ + res + * HTTP/1.0\r\n\r\n” ;

62

63 // send HTTP request

64 os.write(send.getBytes());

65

66 // read response

67 len = is.read(recv);

68

69 // close connection

70 sock.close();

71

72 // print results

73 if(len > 0)

74 {

75 // convert recv’d bytes to string..

76 tmp = new String(recv) ;

77

78 // display via stdout

79 System.out.println(tmp );

80 }

81 }

82 catch (NumberFormatException nfe)

83 {

84 // non-numeric port value?

85 System.err.println(“NumberFormatException:”

86 +nfe.getMessage());

87 }

88 catch (IOException           ioe)

89 {

90 // connection failed?

91 System.err.println(“IOException:”

92 + ioe.getMessage());

93 }

94 }

95 }

A constructor is a method that is automatically called when an object is created.
Compilation

C:\> j2sdkl.4.l_02\bin\javac.exe TCPClientl.java

C:\> dir

·

·

TCPClientl.class

·

·

A constructor is a method that is automatically called when an object is created.
Example execution

C:\> j2sdkl.4.l_02\bin\java.exe TCPClientl

usage: java TCPClientl <target_ip> <target__port> <resource>

Example:java TCPClientl 127.0.0.1 80 /

C:\> j2sdkL4.1_02\bin\java.exe TCPClientl 127.0.0.1 80 /

HTTP/1.0 2 00 OK

Server: thttpd/2.23betal 26may2002

Content-Type: text/html; charset=iso-8859-l

Date:Mon, 26 May 2003 06:16:51 GMT

Last-Modified: Thu, 08 May 2003 19:30:33 GM

Accept-Ranges: bytes

Connection: close

Content-Length: 339

In Example 5.1, a TCP client socket is created and connected to an HTTP server on port 80, an HTTP request is sent, and the response is read and then printed to standard out (stdout). This example is useful because it shows the simplicity with which TCP connections are established and used with the Socket class.

Analysis

At line 32, command-line arguments are checked and validated.

At line 51, the Integer parseInt() method is used to convert the port value supplied on the command line to an integer primitive-type suitable for the Socket class constructor.

At line 54, a new Socket instance is created using the Socket constructor and the IP address and port supplied on the command line. The TCP connection is established during this operation. If an error occurs, such as inability to establish the desired connection, an IOException instance is thrown.

At line 57, the InputStream instance that data is read from is retrieved from the Socket instance using the getInputStream() method.

At line 58, the OutputStream instance that data is written from is retrieved from the Socket instance using the getOutputStream() method.

At line 61, the HTTP 1.0 GET request is formatted and stored in the string variable send.

At line 64, the string variable send is converted to a byte array using the String class getBytes() method. The value of this byte array is sent to the Web server using the OutputStream write() method.

At line 67, the InputStream read() method is used to read up to 4096 bytes into the recv byte array. The length of data read from the Web server is stored in the len variable.

At line 70, the connected socket is closed, which results in termination of the TCP connection.

At line 76, if the value of len returned from the InputStream read() method is greater than zero, the recv byte array is converted to a String object.

At line 79, the contents of the recv byte array are printed to stdout.

At line 82, a try-catch handler for the NumberFormatException class is declared. This exception is thrown if the value suppUed for the port on the command line cannot be converted to an integer value by the Integer class constructor at line 51.

At line 88, a try-catch handler for the IOException class is declared. This exception is thrown if an error occurs during estabUshment of a TCP connection, transmission of data, or termination of a TCP connection. Unfortunately, the IOException class does not give reUable, granular error information such as an error code for individual error conditions. Instead, the getMessage() method may be used to obtain a human readable value such as “Connect failed.”

Read full chapter

URL: https://www.sciencedirect.com/science/article/pii/B9781597490054500110

Which method is called automatically when an object is created?

Constructor is a method that is automatically called when an object of a class is created.

Which constructor is automatically called?

They are defined as follows: A constructor is a special initialization function that is automatically called whenever a class is declared. The constructor always has the same name as the class name, and no data types are defined for the argument list or the return type.

When constructor method is called?

It is called when an instance of the class is created. At the time of calling constructor, memory for the object is allocated in the memory. It is a special type of method which is used to initialize the object. Every time an object is created using the new() keyword, at least one constructor is called.